Как правильно представить поповер из UITableViewCell с помощью UIPopoverArrowDirectionRight или UIPopoverArrowDirectionLeft - PullRequest
32 голосов
/ 10 июня 2010

Я всегда пытаюсь представить поповер из ячейки внутри таблицы следующим образом:

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

, но я не могу использовать UIPopoverArrowDirectionRight или Left, потому что, в зависимости от положения ipad (книжной или альбомной)поповер появляется где-то еще.

Правильно ли я представляю поповер?

PS: табличное представление находится в подробном представлении splitView.

Ответы [ 11 ]

49 голосов
/ 22 декабря 2010

Вы получаете кадр из ячейки с помощью метода rectForRowAtIndexPath.Это правильно.Однако табличное представление, скорее всего, является подпредставлением более крупного представления iPad, поэтому, когда поповер получает координаты, он считает, что он находится в увеличенном виде.Вот почему поповер появляется не в том месте.

Например, CGRect для строки (0,40,320,44).Вместо всплывающего окна, нацеленного на этот кадр в табличном представлении, оно вместо этого предназначается для этого кадра в главном представлении.

Я решил эту проблему, преобразовав кадр из относительных координат таблицы в координаты в моем увеличенном виде.

код:

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

Надеюсь, что это поможет другим, кто ищет эту проблему.

22 голосов
/ 11 мая 2011

Сегодня я столкнулся с этой проблемой и нашел более простое решение.
При создании экземпляра popover необходимо указать представление содержимого ячейки:

- (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
}
19 голосов
/ 29 апреля 2015

В Swift, между ответами выше, это работает для меня на iPad в любой ориентации:

if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {

    let cellRect = tableView.rectForRowAtIndexPath(indexPath)

    popOverPresentationController.sourceView                = tableView
    popOverPresentationController.sourceRect                = cellRect
    popOverPresentationController.permittedArrowDirections  = UIPopoverArrowDirection.Any

}
4 голосов
/ 21 июня 2012

Чтобы выскочить поповер рядом с аксессуаром, вы можете использовать этот код:)

Я использую это для более расширенного использования:

  1. находит пользовательский аксессуар View(cell.accesoryView)
  2. если пусто, найти сгенерированный accesoryView (UIButton), если ячейка имеет
  3. , если UIButton не существует, найти контекстное представление ячейки (UITableViewCellContentView)
  4. если представление контекста ячейки не существует, используйте представление ячейки

Можно использовать для UIActionSheet или UIPopoverController .

Вот мой код:

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

Протестировано в iOS 4.3 до 5.1

Лучше всего использовать в качестве пользовательского метода:

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

и код метода:

-(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;
}
3 голосов
/ 15 ноября 2010

Я тоже сталкивался с этой проблемой. Решением для меня было просто изменить ширину прямоугольника, возвращаемого 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]; 

Это создает прямоугольник с центром внутри ячейки. Таким образом, у поповера больше шансов найти хорошее место для позиционирования.

2 голосов
/ 07 декабря 2011

Вот простое решение, которое отлично работает для меня

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

}
2 голосов
/ 06 июля 2010

У меня была такая же проблема, вот обходной путь, который я использовал:

  • в моем UITableViewCell, я добавил Действия (IBActions, когда я генерирую свои ячейки из NIB) для определенных кнопок ячейки.
  • Затем я определил протокол CellActionDelegate, который имитирует мои селекторы действий, к которому у меня были моя кнопка (отправитель) и моя ячейка (self)
  • , затем detailViewController моего splitViewController реализует этот протокол, преобразовывая изячейки с ее координатами ...

вот пример кода

В MyCustomTableViewCell.m:

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

и, в 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: Конечно, «действие» не обязательно должно быть IBAction, а фрейм, из которого происходит всплывающее окно, не обязательно должно быть UIButton - один UIView был бы хорош:)

2 голосов
/ 10 июня 2010

Фрейм ячейки будет выглядеть примерно как 0,0, ширина, размер, я не верю, что он будет иметь свои X и Y относительно tableView ... вы хотите использовать - (CGRect) rectForRowAtIndexPath: (NSIndexPath *) indexPath для этого, это должно вернуть вам правильный кадр для ячейки относительно tableView ... вот ссылка UITAbleView ref

0 голосов
/ 14 сентября 2018

Принятый ответ не может быть скомпилирован.

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];
0 голосов
/ 14 декабря 2014

Это также сработало для меня:


        //Which are the ABSOLUTE coordinates in from the current selected cell
        CGRect frame =[self.view convertRect:[tbvEventsMatch rectForRowAtIndexPath:indexPath] fromView:tbvEventsMatch.viewForBaselineLayout];

...