如何使用 UIPopoverArrowDirectionRight 或 UIPopoverArrowDirectionLeft 从 UITableViewCell 正确呈现弹出框

发布于 2024-09-04 22:37:55 字数 348 浏览 3 评论 0原文

我总是尝试以这种方式从 tableView 内的单元格呈现弹出窗口:

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

但我不能使用 UIPopoverArrowDirectionRight 或 Left,因为,取决于位置 ipad(纵向或横向)时,弹出窗口出现在其他位置。

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

PS:表视图位于 splitView 的详细视图中。

I always try to present a popover from a cell inside a tableView this way:

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

but I cannot use UIPopoverArrowDirectionRight or Left, because, depending on the position
of the ipad (portrait or landscape), the popover appears someplace else.

Am I presenting the popover the right way?

PS: the table view is in the detailView of a splitView.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

晚雾 2024-09-11 22:37:55

您可以通过 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];

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

You're getting the frame from the cell via the rectForRowAtIndexPath method. This is correct. However the tableview is most likely a subview of a larger iPad view so when the popover gets the coordinates it thinks they're in the larger view. This is why the popover appears in the wrong place.

Example, the CGRect for the row is (0,40,320,44). Instead of the popover targeting that frame on the tableview it instead targets that frame on your main view.

I solved this problem by converting the frame from the relative coordinates of the table to coordinates in my larger view.

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

Hope that helps others searching for this issue.

潇烟暮雨 2024-09-11 22:37:55

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

if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {

    let cellRect = tableView.rectForRowAtIndexPath(indexPath)

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

}

In Swift, between the above answers this works for me on an iPad in any orientation:

if let popOverPresentationController : UIPopoverPresentationController = myAlertController.popoverPresentationController {

    let cellRect = tableView.rectForRowAtIndexPath(indexPath)

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

}
π浅易 2024-09-11 22:37:55

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

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

I came across this problem today, and I've found a simpler solution.
When instantiating the popover, you need specify the cell's content view:

- (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
}
墨小沫ゞ 2024-09-11 22:37:55

要在配件旁边弹出弹出窗口,您可以使用此代码:)

我将其用于更高级用途:

  1. 如果为空,则查找自定义的accesoryView(cell.accesoryView)
  2. ,如果单元格有,则查找生成的accesoryView(UIButton)
  3. 如果UIButton不存在,则查找单元格内容视图(UITableViewCellContentView)
  4. 如果单元格内容视图不存在,则使用单元格视图

可用于UIActionSheetUIPopoverController

这是我的代码:

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

To pop a popover next to the accesory u can use this code :)

I use this for more advanced use:

  1. finds custom accesoryView (cell.accesoryView)
  2. if empty, find generated accesoryView (UIButton) if cell has
  3. if the UIButton doesn't exists, find cell contet view (UITableViewCellContentView)
  4. if the cell contet view doesn't exists, use cell view

Can be use for UIActionSheet or UIPopoverController.

Here is my 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];

Tested in iOS 4.3 to 5.1

Best to use as custom method:

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

And method code:

-(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;
}
濫情▎り 2024-09-11 22:37:55

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

这会创建一个在单元格内居中的矩形。这样,弹出窗口就有更多机会找到合适的位置来定位自己。

I did come across this problem as well. A solution for me was to simply change the width of the rect returned by 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]; 

This create a rect centred inside the cell. This way, the popover has more chances of findind a good spot to position itself.

橘寄 2024-09-11 22:37:55

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

  • 在我的 UITableViewCell 中,我为单元格的特定按钮添加了操作(当我从 NIB 生成单元格时为 IBActions)。
  • 然后我定义了一个模仿我的动作选择器的 CellActionDelegate 协议,我有我的按钮(发送者)和我的单元格(自身),
  • 然后我的 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 就很好了:)

I had the same kind of problem, here's the workaround i used :

  • in my UITableViewCell, i added Actions (IBActions as i generate my cells from a NIB) for cell's specific buttons.
  • i then defined a CellActionDelegate protocol that mimics my actions selectors, to which i had my button (sender) and my cell (self)
  • then the detailViewController of my splitViewController implements this protocol, converting from the cell's to its coordinates...

here a example of code

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

and the, 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 : Of course, the 'action' doesn't have to be a IBAction, and the frame from where the popover originates doesn't have to be a UIButton - a single UIView would be good :)

离不开的别离 2024-09-11 22:37:55

这是对我来说效果很好的简单解决方案

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

}

Here is the simple solution which works fine for 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];

}
难忘№最初的完美 2024-09-11 22:37:55

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

The cell frame is going to be something like 0,0,width,size, i dont believe it will have its X and Y relative to the tableView...you want to use - (CGRect)rectForRowAtIndexPath:(NSIndexPath *)indexPath for this, this should return you the correct frame for the cell relative to the tableView...here is a link UITAbleView ref

空宴 2024-09-11 22:37:55

接受的答案现在无法编译。

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

The accepted answer cannot compile now.

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];
眼眸里的那抹悲凉 2024-09-11 22:37:55

这就是我所做的并且工作得很好。

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

This is how i did and works perfectly fine.

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];
九公里浅绿 2024-09-11 22:37:55

这也对我有用:

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

This also worked for me:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文