2010-06-10 26 views
31

J'essaie toujours de présenter un popover d'une cellule à l'intérieur d'une tableView façon suivante:Comment présenter correctement un popover d'un UITableViewCell avec UIPopoverArrowDirectionRight ou UIPopoverArrowDirectionLeft

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

mais je ne peux pas utiliser UIPopoverArrowDirectionRight ou à gauche, parce que, selon sur la position de l'ipad (portrait ou paysage), le popover apparaît ailleurs. Est-ce que je présente le popover de la bonne manière? PS: la vue de table est dans la vue détaillée d'un splitView.

+0

comment voulez-vous instancier myPopover? –

Répondre

3

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

} 
+8

Que signifie 600 signifie? –

+0

Cela indiquerait que l'origine du rectangle de présentation est 600 à droite de l'origine des limites de la cellule (et 10 à partir du haut de l'origine de la cellule). Vous pouvez les ajuster pour placer la présentation de n'importe où dans votre cellule. –

+39

La plupart des gens ne devraient pas faire cela. N'utilisez jamais de nombres codés en dur comme celui-ci, et cela ne fonctionnerait pas lorsque l'orientation changerait. –

2

Le cadre de la cellule va être quelque chose comme 0,0, largeur, 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

+0

Salut! merci pour la réponse .. mais avec la méthode que vous recommandez je reçois le même CGrect, et j'ai toujours le problème avec la position du popover. Lorsque l'ipad est en mode portrait, le survol apparaît dans le coin supérieur gauche de l'écran lorsque je spécifie les directions de la flèche ... ça me fait peur !!! .. Par contre, est-il correct de le présenter à partir de self.TableView? Merci quand même – Omer

2

J'ai eu le même genre de problème, voici la solution i utilisé:

  • dans mon UITableViewCell, j'ai ajouté Actions (IBActions comme je génère mes cellules à partir d'un NIB) pour les boutons spécifiques de la cellule.
  • 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 mon splitViewController implémente ce protocole, la conversion de ses coordonnées de la cellule ...

ici un exemple de code de

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 le, 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 unique serait bon :)

+0

Hey .. merci, je vais essayer ...cela semble une solution de contournement intelligente jeje – Omer

3

J'ai également rencontré ce problème. Une solution pour moi était de changer simplement la largeur du rect retourné 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]; 

Ce créer un rect centré à l'intérieur de la cellule. De cette façon, le popover a plus de chances de trouver un bon endroit pour se positionner.

+0

J'ai utilisé cette méthode pour attacher une ActionSheet au detailText d'une tableviewcell sur un iPad. 'CGRect rectToUse = targetCell.bounds; rectToUse.origin.x = rectToUse.size.width - 200; rectToUse.size.width - = rectToUse.origin.x; ' – casey

46

Vous obtenez le cadre de la cellule via la méthode rectForRowAtIndexPath. C'est correct. Cependant, la vue de table est probablement une sous-vue d'une vue iPad plus grande, donc quand le popover obtient les coordonnées, il pense qu'il est dans une vue plus grande. C'est pourquoi le popover apparaît au mauvais endroit.

Exemple, le CGRect pour la ligne est (0,40,320,44). Au lieu de la popover ciblant ce cadre sur la tableview, il cible plutôt ce cadre sur votre vue principale.

J'ai résolu ce problème en convertissant la trame à partir des coordonnées relatives de la table en coordonnées dans ma plus grande vue.

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

Espoir qui aide les autres à la recherche de cette question.

+0

Cela a résolu mon problème en travaillant en mode portrait, mais pas en mode paysage. Merci –

+0

Résoudre mon problème aussi –

+0

Ceci est certainement utile. Je recevais le cadre de la cellule elle-même, '[tableView cellForRowAtIndexPath: indexPath]', ce qui est une mauvaise chose à faire. N'a même pas conscience de '-rectForRowAtIndexPath:'. Merci! – user1244109

20

J'ai rencontré ce problème aujourd'hui, et j'ai trouvé une solution plus simple.
l'instanciation popover, vous devez préciser le point de vue du 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 
} 
+1

Juste une question, pouvez-vous instancier un UIPopoverController en utilisant cette méthode avec seulement un UIVew? Mauvais; Essayez-le = D – Omer

+0

@Omer Je ne sais pas ce que vous voulez dire par là. Pouvez-vous clarifier? – antalkerekes

+0

C'est la bonne réponse. La documentation de presentPopoverFromRect indique que le rect est le rectangle en vue auquel ancrer la fenêtre popover et la vue est la vue contenant le rectangle d'ancrage pour le popover, donc c'est en fait plus simple qu'il n'y paraît! – Clafou

3

Pour apparaître un popover à côté du accesory u peut utiliser ce code :)

J'utilise cela pour plus utilisation avancée:

  1. trouve accesoryView personnalisé (cell.accesoryView)
  2. si elle est vide, trouver généré accesoryView (UIButton) si la cellule a
  3. si le UIButton n'existe pas, trouver une vue de Contet cellulaire (UITableViewCellContentView)
  4. si la cellule vue Contet n'existe pas, utilisez la vue des cellules

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és dans iOS 4.3 à 5,1

utiliser au mieux 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; 
} 
+1

Testé fonctionnant dans iOS6SDK. Je n'ai pas essayé la méthode personnalisée, juste dans le ViewController- (void) tableView: (UITableView *) tableView accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *) indexPath –

0

Voici comment j'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]; 
0

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

13

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 

} 
+0

C'est sympa si vous voulez configurer le segue dans un Storyboard. Vous pouvez simplement définir la propriété sourceRect à partir de la méthode prepareForSegue :. – Joony