如何使用UIPopoverArrowDirectionRight或UIPopoverArrowDirectionLeft从UITableViewCell正确显示弹出窗口

时间:2010-06-10 14:35:37

标签: objective-c ipad uipopovercontroller popover

我总是尝试以这种方式从tableView中的单元格呈现一个popover:

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

但我不能使用UIPopoverArrowDirectionRight或Left,因为,取决于位置 在ipad(肖像或风景)中,popover出现在其他地方。

我是否以正确的方式呈现了弹出窗口?

PS:表视图位于splitView的detailView中。

10 个答案:

答案 0 :(得分:49)

您通过rectForRowAtIndexPath方法从单元格中获取帧。这是对的。然而,tableview很可能是更大的iPad视图的子视图,所以当popover获得坐标时,它认为它们在更大的视图中。这就是为什么popover出现在错误的地方。

例如,该行的CGRect是(0,40,320,44)。而不是在tableview上定位该框架的popover,而是在主视图上定位该框架。

我通过将帧从表格的相对坐标转换为较大视图中的坐标来解决此问题。

代码:

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

希望能帮助其他人搜索此问题。

答案 1 :(得分:22)

我今天遇到了这个问题,我找到了一个更简单的解决方案 实例化弹出框时,您需要指定单元格的内容视图:

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

答案 2 :(得分:18)

在Swift中,在上述答案之间,这适用于我在iPad上的任何方向:

if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {

    let cellRect = tableView.rectForRowAtIndexPath(indexPath)

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

}

答案 3 :(得分:4)

要弹出附件旁边的弹出窗口,您可以使用以下代码:)

我将此用于更多高级用途:

  1. 找到自定义accesoryView(cell.accesoryView)
  2. 如果为空,如果单元格
  3. ,则找到生成的accesoryView(UIButton)
  4. 如果UIButton不存在,找到单元格上下文视图(UITableViewCellContentView)
  5. 如果单元格竞争视图不存在,请使用单元格视图
  6. 可用于 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;
    }
    

答案 4 :(得分:3)

我也遇到过这个问题。对我来说,一个解决方案就是简单地改变由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]; 

这将创建一个以单元格为中心的矩形。通过这种方式,popover有更多的机会找到一个定位自己的好地方。

答案 5 :(得分:2)

单元格框架将类似于0,0,宽度,大小,我不相信它将具有相对于tableView的X和Y ...您想要使用 - (CGRect)rectForRowAtIndexPath:(NSIndexPath * )indexPath为此,这应该返回相对于tableView的单元格的正确框架...这里是一个链接UITAbleView ref

答案 6 :(得分:2)

我遇到了同样的问题,这是我使用的解决方法:

  • 在我的UITableViewCell中,我添加了Actions(IBActions,因为我从NIB生成我的单元格),用于单元格的特定按钮。
  • 然后我定义了一个模仿我的动作选择器的CellActionDelegate协议,我有我的按钮(发送者)和我的单元格(自我)
  • 然后我的splitViewController的detailViewController实现了这个协议,从单元格转换到它的坐标......

这里是一个代码示例

在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会很好:)

答案 7 :(得分:2)

这是一个对我来说很好的简单解决方案

- (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 :(得分:0)

这就是我的表现并且完美无缺。

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

答案 9 :(得分:0)

这对我也很有用:


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