Cómo presentar correctamente un popover de un UITableViewCell con UIPopoverArrowDirectionRight o UIPopoverArrowDirectionLeft
-
26-09-2019 - |
Pregunta
Siempre tratar de presentar un popover de una célula dentro de un tableView de esta manera:
[myPopover presentPopoverFromRect:cell.frame inView:self.tableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
pero no puedo utilizar UIPopoverArrowDirectionRight o izquierda, ya que, dependiendo de la posición del iPad (vertical u horizontal), el popover aparece en otro lugar.
I Am presentar el popover de la manera correcta?
PS:. La vista de tabla se encuentra en la DetailView de un SPLITVIEW
Solución
Aquí está la solución simple que funciona bien para mí
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
CGRect rect=CGRectMake(cell.bounds.origin.x+600, cell.bounds.origin.y+10, 50, 30);
[popOverController presentPopoverFromRect:rect inView:cell permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Otros consejos
que está recibiendo el marco de la célula a través del método rectForRowAtIndexPath. Esto es correcto. Sin embargo, el tableview más probable es una vista secundaria de una vista más grande del iPad así que cuando el popover obtiene las coordenadas se piensa que están en la vista más grande. Esta es la razón por la popover aparece en el lugar equivocado.
ejemplo, el CGRect para la fila es (0,40,320,44). En lugar de la popover la orientación de ese marco en el que tableview lugar se dirige a ese marco en su vista principal.
Me solucionó este problema mediante la conversión del marco de las coordenadas relativas de la tabla de coordenadas en mi opinión más grande.
código:
CGRect aFrame = [self.myDetailViewController.tableView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:theRow inSection:1]];
[popoverController presentPopoverFromRect:[self.myDetailViewController.tableView convertRect:aFrame toView:self.view] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
Espero que ayude a otros en busca de este problema.
Me encontré con este problema hoy en día, y he encontrado una solución más simple.
Cuando una instancia del popover, es necesario especificar la vista del contenido de la celda:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *aViewController = [[UIViewController alloc] init];
// initialize view here
UIPopoverController *popoverController = [[UIPopoverController alloc]
initWithContentViewController:aViewController];
popoverController.popoverContentSize = CGSizeMake(320, 416);
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[popoverController presentPopoverFromRect:cell.bounds inView:cell.contentView
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
[aView release];
// release popover in 'popoverControllerDidDismissPopover:' method
}
En Swift, entre las respuestas anteriores esto funciona para mí en un iPad en cualquier orientación:
if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {
let cellRect = tableView.rectForRowAtIndexPath(indexPath)
popOverPresentationController.sourceView = tableView
popOverPresentationController.sourceRect = cellRect
popOverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.Any
}
para que aparezca un popover al lado del accesorio u puede utilizar este código:)
Yo lo uso para más uso avanzado:
- encuentra accesoryView personalizado (cell.accesoryView)
- Si está vacío, encontrar generada accesoryView (UIButton) si la celda tiene
- Si no existe la UIButton, Vista Contet celular (UITableViewCellContentView)
- Si no existe la vista Contet celular, en opinión de células uso
Puede ser el uso de UIActionSheet o UIPopoverController .
Aquí está mi código:
UIView *accessoryView = cell.accessoryView; // finds custom accesoryView (cell.accesoryView)
if (accessoryView == nil) {
UIView *cellContentView = nil;
for (UIView *accView in [cell subviews]) {
if ([accView isKindOfClass:[UIButton class]]) {
accessoryView = accView; // find generated accesoryView (UIButton)
break;
} else if ([accView isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {
// find generated UITableViewCellContentView
cellContentView = accView;
}
}
// if the UIButton doesn't exists, find cell contet view (UITableViewCellContentView)
if (accessoryView == nil) {
accessoryView = cellContentView;
}
// if the cell contet view doesn't exists, use cell view
if (accessoryView == nil) {
accessoryView = cell;
}
}
[actionSheet showFromRect:accessoryView.bounds inView:accessoryView animated:YES];
Probado en iOS 4.3 a 5.1
Lo mejor es utilizar como método personalizado:
-(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell;
Y el código método:
-(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell {
UIView *accessoryView = cell.accessoryView;
if (accessoryView == nil) {
UIView *cellContentView = nil;
for (UIView *accView in [cell subviews]) {
if ([accView isKindOfClass:[UIButton class]]) {
accessoryView = accView;
break;
} else if ([accView isKindOfClass:NSClassFromString(@"UITableViewCellContentView")]) {
cellContentView = accView;
}
}
if (accessoryView == nil) {
accessoryView = cellContentView;
}
if (accessoryView == nil) {
accessoryView = cell;
}
}
return accessoryView;
}
Me llegó a través de este problema también. Una solución para mí fue simplemente cambiar la anchura de la rect devuelto por CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath
:
CGRect rect = [aTableView rectForRowAtIndexPath:indexPath];
//create a 10 pixel width rect at the center of the cell
rect.origin.x = (rect.size.width - 10.0) / 2.0;
rect.size.width = 10.0;
[self.addExpensePopoverController presentPopoverFromRect:rect inView:aTableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
Esto crea un rect centrado dentro de la célula. De esta manera, el popover tiene más posibilidades de findind un lugar bueno para posicionarse.
El marco celular va a ser algo así como 0,0, anchura, tamaño, yo no creo que va a tener su X e Y con respecto a la tableView ... que desea utilizar - (CGRect) rectForRowAtIndexPath: (* NSIndexPath ) indexPath para esto, esto debe devolver el marco correcto para la célula en relación con el tableView ... aquí hay un enlace UITableView ref
Yo tenía el mismo tipo de problema, aquí está la solución que utilicé:
- en mi UITableViewCell, añadí acciones (IBActions como genero mis células de una mina) para los botones específicos de células.
- i define entonces un protocolo CellActionDelegate que imita mis acciones selectores, a la que i tenía mi botón (emisor) y la celda (auto)
- entonces el detailViewController de mis implementos splitViewController este protocolo, la conversión de la célula es a su coordenadas ...
aquí un ejemplo de código
En MyCustomTableViewCell.m:
-(IBAction)displaySomeCellRelativePopover:(id)sender{
//passes the actions to its delegate
UIButton *button = (UIButton *)sender;
[cellActionDelegate displaySomeCellRelativePopoverWithInformation:self.info
fromButton:button
fromCell:self];
}
y, en MyDetailViewController.m:
-(void)displaySomeCellRelativePopoverWithInformation:(MyCellInformationClass *)info
fromButton:(UIButton *)button
fromCell:(UIView *)cell{
UIPopoverController * popoverController = nil;
//create your own UIPopoverController the way you want
//Convert your button/view frame
CGRect buttonFrameInDetailView = [self.view convertRect:button.frame fromView:cell];
//present the popoverController
[popoverController presentPopoverFromRect:buttonFrameInDetailView
inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];]
//release objects created...
}
PS: Por supuesto, la 'acción' no tiene que ser un IBAction, y el marco desde donde se origina el popover no tiene que ser un UIButton - una sola UIView sería bueno:)
Esta es la forma en que lo hice y funciona perfectamente bien.
RidersVC *vc = [RidersVC ridersVC];
vc.modalPresentationStyle = UIModalPresentationPopover;
vc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
UIPopoverPresentationController *popPresenter = [vc popoverPresentationController];
popPresenter.sourceView = vc.view;
popPresenter.barButtonItem= [[UIBarButtonItem alloc] initWithCustomView:button];
popPresenter.backgroundColor = [UIColor colorWithRed:220.0f/255.0f green:227.0f/255.0f blue:237.0f/255.0f alpha:1.0];
[self.parentVC presentViewController:vc animated:YES completion:NULL];
Esto también trabajó para mí:
//Which are the ABSOLUTE coordinates in from the current selected cell CGRect frame =[self.view convertRect:[tbvEventsMatch rectForRowAtIndexPath:indexPath] fromView:tbvEventsMatch.viewForBaselineLayout];
La respuesta aceptada no puede compilar ahora.
CGRect rect =[tableView rectForRowAtIndexPath:indexPath]; //This is how to get the correct position on the tableView
UIPopoverPresentationController *popController = [controller popoverPresentationController];
popController.sourceRect = rect;
popController.permittedArrowDirections = 0; //Here there is no arrow. It is my app's need
popController.delegate = self;
popController.sourceView = self.tableView;
popController.sourceView.backgroundColor = [UIColor yellowColor];