如何让 iOS 弹出框视图在气泡中正确定位

How to get iOS popover view to position correctly within the bubble

提问人:Agent Friday 提问时间:10/13/2023 更新时间:10/13/2023 访问量:46

问:

我编写了代码,以便在 UICollectionView 单元格被选中但由于某种原因不可用时显示该单元格中的弹出框。它工作正常,只是内容从未在弹出气泡中正确定位。请注意,从所示的两个示例中可以看出,内容总是以大约一半厚度的厚度向插入符号移动。

enter image description here enter image description here

很明显,大小计算正确,但似乎弹出框控制器只是错误地计算了 popupView 的位置。由于移位方向超出了我的控制范围,因此我不能将所有内容都移位几个像素作为解决方法。

情节提要只有一个 popupView,其中包含在场景视图中水平和垂直居中的约束:

enter image description here

这是我的代码......请注意,我打开了视图周围的边框,只是为了突出这种偏移。

// Inside collectionView:didSelectItemAtIndexPath:

    UIStoryboard* mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    MenuUnavailableViewController* muc = [mainStoryboard instantiateViewControllerWithIdentifier:@"MenuOptionUnavailable"];
    muc.modalPresentationStyle = UIModalPresentationPopover;

    [self presentViewController:muc animated:NO completion:nil];

    MenuCollectionViewCell* menuCell = (MenuCollectionViewCell*) [menuCollection cellForItemAtIndexPath:indexPath];
    muc.popoverPresentationController.sourceView = menuCollection;
    muc.popoverPresentationController.sourceRect = menuCell.frame;
    muc.popoverPresentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
@implementation MenuUnavailableViewController

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
   
    [self.view layoutSubviews];
    self.preferredContentSize = self.popupView.bounds.size;
    self.popupView.layer.borderColor = [UIColor blackColor].CGColor;
    self.popupView.layer.borderWidth = 2;
    self.popupView.layer.cornerRadius = 12;
}

我已经使用这个公式成功地做了一段时间的弹出窗口,然后有一天一些 iOS 或 Xcode 更新悄悄地打破了定位(不确定,但我认为是在 iOS 13 或 14 左右)。有人知道我做错了什么吗?我一直在寻找一个在最新的 iOS 版本下实现弹出框的完整示例,但在任何地方都找不到。

iOS Objective-C UIPopOverController

评论


答:

0赞 DonMag 10/13/2023 #1

不知道发生了什么变化,或者什么时候......而且,也许你的布局“很幸运”,所以你没有注意到它......但。。。

我们希望根据控制器视图的大小来设置 - 而不是您的子视图。.preferredContentSizepopupView

此外,我们希望确保内容被限制在安全区域内。

所以,如果我像这样设置:MenuUnavailableViewController

enter image description here

使用“不可用”和“原因:”标签,内容拥抱和抗压缩优先级都设置为......Required

  • Unavailable Lbl标签将确定宽度
  • “Reason Lbl”标签将决定高度

在调用控制器中,设置标签的字符串属性。

然后,类如下所示:MenuUnavailableViewController

@implementation MenuUnavailableViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    self.unavailableLbl.text = _unavailableString;
    self.reasonLbl.text = _reasonString;
    
    self.preferredContentSize = [self.view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
}

@end

无需在 中执行任何操作。viewWillAppear

下面是它的外观(循环浏览 3 组字符串):

enter image description here

enter image description here

enter image description here

如果我们清除颜色和边框:

enter image description here

enter image description here

enter image description here

而且,只是为了表明它适用于不同的“箭头”方向:

enter image description here

enter image description here

enter image description here

enter image description here