Cómo presentar correctamente un popover de un UITableViewCell con UIPopoverArrowDirectionRight o UIPopoverArrowDirectionLeft

StackOverflow https://stackoverflow.com/questions/3015400

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

¿Fue útil?

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:

  1. encuentra accesoryView personalizado (cell.accesoryView)
  2. Si está vacío, encontrar generada accesoryView (UIButton) si la celda tiene
  3. Si no existe la UIButton, Vista Contet celular (UITableViewCellContentView)
  4. 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];
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top