objective c - Cómo presentar correctamente un popover desde una UITableViewCell con UIPopoverArrowDirectionRight o UIPopoverArrowDirectionLeft
objective-c ipad (10)
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];
}
Siempre intento presentar un popover desde una celda dentro de una mesa. Ver de esta manera:
[myPopover presentPopoverFromRect:cell.frame inView:self.tableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
pero no puedo usar UIPopoverArrowDirectionRight o Left, porque, dependiendo de la posición del ipad (retrato o paisaje), el popover aparece en otro lugar.
¿Estoy presentando el popover de la manera correcta?
PD: la vista de tabla se encuentra en la vista detallada de una vista dividida.
Así es como 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];
El recuadro de la celda va a ser algo así como 0,0, ancho, tamaño, no creo que tenga su X e Y en relación con la vista de tabla ... usted quiere usar - (CGRect) rectForRowAtIndexPath: (NSIndexPath *) indexPath para esto, esto debería devolverle el marco correcto para la celda relativa a la vista de tabla ... aquí hay un enlace UITAbleView ref
En Swift, entre las respuestas anteriores, esto funciona para mí en un iPad con cualquier orientación:
if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {
let cellRect = tableView.rectForRowAtIndexPath(indexPath)
popOverPresentationController.sourceView = tableView
popOverPresentationController.sourceRect = cellRect
popOverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.Any
}
Esto también funcionó para mí:
//Which are the ABSOLUTE coordinates in from the current selected cell CGRect frame =[self.view convertRect:[tbvEventsMatch rectForRowAtIndexPath:indexPath] fromView:tbvEventsMatch.viewForBaselineLayout];
Hoy me encontré con este problema y encontré una solución más simple.
Al crear instancias del popover, debe especificar la vista de 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
}
Me encontré con este problema también. Una solución para mí fue simplemente cambiar el ancho del 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 recto centrado dentro de la celda. De esta manera, el popover tiene más posibilidades de encontrar un buen lugar para posicionarse.
Obtendrá el marco de la celda a través del método rectForRowAtIndexPath. Esto es correcto. Sin embargo, es muy probable que la vista de tabla sea una subvista de una vista de iPad más grande, por lo que cuando el popover obtiene las coordenadas cree que están en la vista más grande. Esta es la razón por la cual el popover aparece en el lugar equivocado.
Ejemplo, el CGRect para la fila es (0,40,320,44). En lugar de que Popover se dirija a ese fotograma en la vista de tabla, en su lugar apunta a ese fotograma en su vista principal.
Resolví este problema convirtiendo el marco de las coordenadas relativas de la tabla a coordenadas en mi vista 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 a buscar este problema.
Para hacer estallar un popover al lado del accesorio, puedes usar este código :)
Lo uso para un uso más avanzado:
- encuentra accesoryView personalizado (cell.accesoryView)
- si está vacío, busque accesoryView generado (UIButton) si la celda tiene
- si el UIButton no existe, busque cell contet view (UITableViewCellContentView)
- si la vista contet de celda no existe, use la vista de celda
Se puede usar para 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
Es mejor utilizarlo como método personalizado:
-(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell;
Y código de 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;
}
Tuve el mismo tipo de problema, aquí está la solución que utilicé:
- en mi UITableViewCell, agregué Acciones (IBActions cuando genero mis celdas desde un NIB) para los botones específicos de la celda.
- Luego definí un protocolo CellActionDelegate que imita mis selectores de acciones, al cual tenía mi botón (remitente) y mi celda (auto)
- entonces el detalleViewController de mi splitViewController implementa este protocolo, convirtiendo de la celda a sus 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 el, 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...
}
PD: Por supuesto, la "acción" no tiene que ser un IBAction, y el fotograma desde el que se origina el popover no tiene que ser un UIButton, una sola UIView sería buena :)