Come presentare correttamente un popover da UITableViewCell con UIPopoverArrowDirectionRight o UIPopoverArrowDirectionLeft

Cerco sempre di presentare un popover da una cella all’interno di una tabellaVisualizza in questo modo:

[myPopover presentPopoverFromRect:cell.frame inView:self.tableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; 

ma non posso usare UIPopoverArrowDirectionRight o Left, perché, a seconda della posizione dell’ipad (verticale o orizzontale), il popover appare altrove.

Sto presentando il popover nel modo giusto?

PS: la vista tabella è nel dettaglioVista di splitView.

Ecco la soluzione semplice che funziona bene per me

 - (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]; } 

Stai ottenendo il frame dalla cella tramite il metodo rectForRowAtIndexPath. Questo è corretto. Tuttavia, la vista tabella è molto probabilmente una sottoview di una vista iPad più grande, quindi quando il popover ottiene le coordinate che pensa siano nella vista più grande. Questo è il motivo per cui il popover appare nel posto sbagliato.

Esempio, il CGRect per la riga è (0,40,320,44). Invece del popover che prende di mira quel fotogramma sulla vista tabella, punta invece a quel fotogramma sulla tua vista principale.

Ho risolto questo problema convertendo il frame dalle coordinate relative della tabella alle coordinate nella mia vista ingrandita.

codice:

 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]; 

Spero che aiuti gli altri a cercare questo problema.

Mi sono imbattuto in questo problema oggi e ho trovato una soluzione più semplice.
Quando si istanzia il popover, è necessario specificare la vista del contenuto della cella:

 - (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 } 

In Swift, tra le risposte di cui sopra questo funziona per me su un iPad in qualsiasi orientamento:

 if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController { let cellRect = tableView.rectForRowAtIndexPath(indexPath) popOverPresentationController.sourceView = tableView popOverPresentationController.sourceRect = cellRect popOverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.Any } 

Per far apparire un popover vicino all’accessorio puoi usare questo codice 🙂

Lo uso per un uso più avanzato:

  1. trova personalizzato accesoryView (cell.accesoryView)
  2. se vuoto, trova generato accesoryView (UIButton) se la cella ha
  3. se UIButton non esiste, trova la vista contet delle celle (UITableViewCellContentView)
  4. se la vista contet delle celle non esiste, utilizzare la visualizzazione cella

Può essere utilizzato per UIActionSheet o UIPopoverController .

Ecco il mio codice:

 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]; 

Testato su iOS 4.3 a 5.1

Meglio usare come metodo personalizzato:

 -(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell; 

E il codice del metodo:

 -(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; } 

Ho incontrato anche questo problema. Una soluzione per me era semplicemente cambiare la larghezza del rect restituito da 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]; 

Questo crea un retto centrato all’interno della cella. In questo modo, il popover ha più possibilità di trovare un buon posto per posizionarsi.

Il frame della cella sarà qualcosa come 0,0, width, size, non credo che avrà la sua X e Y rispetto al tableView … che vuoi usare – (CGRect) rectForRowAtIndexPath: (NSIndexPath *) indexPath per questo, questo dovrebbe restituirti il ​​frame corretto per la cella relativo al tableView … ecco un link UITAbleView ref

Ho avuto lo stesso tipo di problema, ecco la soluzione che ho usato:

  • nel mio UITableViewCell, ho aggiunto Azioni (IBActions come faccio a generare le mie celle da un NIB) per i pulsanti specifici della cella.
  • Ho quindi definito un protocollo CellActionDelegate che simula i miei selettori di azioni, a cui ho avuto il mio pulsante (mittente) e la mia cella (auto)
  • quindi il detailViewController del mio splitViewController implementa questo protocollo, convertendo dalla cella alle sue coordinate …

qui un esempio di codice

In MyCustomTableViewCell.m:

  -(IBAction)displaySomeCellRelativePopover:(id)sender{ //passes the actions to its delegate UIButton *button = (UIButton *)sender; [cellActionDelegate displaySomeCellRelativePopoverWithInformation:self.info fromButton:button fromCell:self]; } 

e il, in 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: Ovviamente, l’azione non deve essere una IBAction, e il frame da cui proviene il popover non deve essere un UIButton – un singolo UIView sarebbe buono 🙂

Questo è come ho fatto e funziona perfettamente.

 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]; 

Questo ha funzionato anche per me:

         // Quali sono le coordinate ABSOLUTE dalla cella selezionata corrente
         CGRect frame = [self.view convertRect: [tbvEventsMatch rectForRowAtIndexPath: indexPath] fromView: tbvEventsMatch.viewForBaselineLayout];