Comment présenter correctement un popover d'un UITableViewCell avec UIPopoverArrowDirectionRight ou UIPopoverArrowDirectionLeft
-
26-09-2019 - |
Question
J'essaie toujours de présenter un popover d'une cellule à l'intérieur d'une tableView de cette façon:
[myPopover presentPopoverFromRect:cell.frame inView:self.tableView permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
mais je ne peux pas utiliser UIPopoverArrowDirectionRight ou à gauche, parce que, selon la position de l'iPad (portrait ou paysage), le popover apparaît ailleurs.
Suis-je présenter le popover la bonne façon?
PS:. L'affichage du tableau est dans le DetailView d'un SPLITVIEW
La solution
Voici la solution simple qui fonctionne bien pour moi
- (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];
}
Autres conseils
Vous obtenez le cadre de la cellule via la méthode rectForRowAtIndexPath. C'est correct. Cependant, le tableview est très probablement une sous-vue d'une vue iPad plus alors quand le popover obtient les coordonnées qu'il pense qu'ils sont dans la plus grande vue. Ceci est la raison pour laquelle l'popover apparaît au mauvais endroit.
Exemple, le CGRect de la ligne est (0,40,320,44). Au lieu de l'popover ciblage sur le cadre tableview il cible plutôt que cadre sur votre écran principal.
I a résolu ce problème en convertissant la trame à partir des coordonnées relatives de la table à coordonnées selon moi plus grande.
code:
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];
L'espoir qui aide les autres à la recherche de cette question.
Je suis tombé sur ce problème aujourd'hui, et je l'ai trouvé une solution plus simple.
Lors de l'instanciation du popover, vous devez spécifier afficher le contenu de la cellule:
- (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
}
Dans Swift, entre les réponses ci-dessus Cela fonctionne pour moi sur un iPad dans une orientation:
if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {
let cellRect = tableView.rectForRowAtIndexPath(indexPath)
popOverPresentationController.sourceView = tableView
popOverPresentationController.sourceRect = cellRect
popOverPresentationController.permittedArrowDirections = UIPopoverArrowDirection.Any
}
Pour faire apparaître un popover à côté de la accesory u peut utiliser ce code:)
J'utilise cela pour plus utilisation avancée:
- trouve accesoryView personnalisé (cell.accesoryView)
- si elle est vide, trouver généré accesoryView (UIButton) si la cellule a
- si le UIButton n'existe pas, trouver une vue de Contet cellulaire (UITableViewCellContentView)
- si la vue Contet cellulaire n'existe pas, utilisez la vue cellulaire
Peut être utilisé pour UIActionSheet ou UIPopoverController .
Voici mon code:
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];
Testé dans iOS 4/3 à 5/1
Il vaut mieux utiliser comme méthode personnalisée:
-(UIView*)getViewForSheetAndPopUp:(UITableViewCell*)cell;
et le code de la méthode:
-(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;
}
Je n'ai rencontré ce problème aussi bien. Une solution pour moi était de changer simplement la largeur de la rect retournée par 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];
créer une rect centrée à l'intérieur de la cellule. De cette façon, le popover a plus de chances de findind un bon endroit pour se positionner.
Le cadre cellulaire va être quelque chose comme 0,0, la largeur, la taille, je ne crois pas qu'il aura son X et Y par rapport à la tableView ... vous voulez utiliser - (CGRect) rectForRowAtIndexPath: (NSIndexPath * ) indexPath pour cela, cela devrait vous retourner le cadre approprié pour la cellule par rapport à la tableView ... voici un lien uitableview ref
J'ai eu le même genre de problème, voici la solution i utilisé:
- dans mon UITableViewCell, j'ajouté Actions (IBActions que je produis mes cellules d'un NIB) pour les boutons spécifiques de cellules.
- i alors défini un protocole de CellActionDelegate qui imite mes actions sélecteurs, que j'avais mon bouton (émetteur) et ma cellule (auto)
- alors la detailViewController de mes splitViewController implémente ce protocole, la conversion de la cellule est à ses coordonnées ...
ici un exemple de code
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];
}
et, 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: Bien sûr, la « action » ne doit pas être un IBAction, et le cadre d'où provient le popover ne doit pas être un UIButton - un UIView serait bon:)
Voici comment je l'ai fait et fonctionne parfaitement 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];
Cela a également travaillé pour moi:
//Which are the ABSOLUTE coordinates in from the current selected cell CGRect frame =[self.view convertRect:[tbvEventsMatch rectForRowAtIndexPath:indexPath] fromView:tbvEventsMatch.viewForBaselineLayout];
La réponse acceptée ne peut pas compiler maintenant.
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];