iOS 13中,UIPopoverPresentationController 中的箭头 arrow
的frame
包含在了vc.view
中。导致以前正常的布局在iOS 13
上错误显示。
文后有补充约束的方式!!!
iOS 13截图
![](https://img.haomeiwen.com/i2571591/5041126a0d62b3e7.png)
iOS 12截图
![](https://img.haomeiwen.com/i2571591/8e9f680d3f8a922f.png)
先贴一段测试代码,方便更好的理解
@implementation ViewController
- (void)showVC:(UIButton *)button
{
PresentatedViewController *vc = [[PresentatedViewController alloc] init];
vc.preferredContentSize = CGSizeMake(300, 300);
vc.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *pvc = vc.popoverPresentationController;
pvc.permittedArrowDirections = UIPopoverArrowDirectionDown;
pvc.sourceView = button;
pvc.sourceRect = button.bounds;
[self presentViewController:vc animated:YES completion:nil];
}
在iOS 13
上,仔细对比发现存在以下变化:
1. vc.preferredContentSize 设置的大小为 {300, 300}。但是当你设置箭头方向在左或在右时
'permittedArrowDirections = UIPopoverArrowDirectionLeft/ UIPopoverArrowDirectionRight',
你的`contentSize.width` 会增加13pt,变为{313, 300}。
同理方向为上或下时,`contentSize.height` 会增加13pt,变为{3, 313}。
2. 从`1`中看出,arrow包含在了vc中,并且vc会自动在响应的方向上增加13pt。从而造成添加在`vc.view`
上的视图被遮挡或者显示不完全的效果。
以上问题经笔者Google最终在twitter
上有说明,这不是一个bug,而且苹果这次的一个特性,类似于UIViewController
的safeArea
的特性。
最终经笔者查阅苹果开发文档与安全区域相关联的属性和多次尝试后找到最终解决的钥匙!!!
解决代码如下:
@implementation PresentatedViewController
- (void)loadView
{
[super loadView];
[self setupViews];
}
- (void)setupViews
{
self.view.backgroundColor = [UIColor greenColor];
self.bgView = [UIView new];
self.bgView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.bgView];
}
- (void)viewWillLayoutSubviews
{
// 关键点在这里, 这里获取到layoutFrame,使用这个值来布局,就会让出`arrow`所占用的位置。
CGRect layoutFrame = self.view.safeAreaLayoutGuide.layoutFrame;
self.bgView.frame = layoutFrame;
CGRect frame = self.view.frame;
self.bottomView.frame = CGRectMake(0, CGRectGetHeight(frame) - 30, CGRectGetWidth(frame), 30);
[super viewWillLayoutSubviews];
}
@end
关键点就在 self.view.safeAreaLayoutGuide
以下是各方向的layoutFrame
pvc.permittedArrowDirections = UIPopoverArrowDirectionLeft
![](https://img.haomeiwen.com/i2571591/26a7cf4d71193f40.png)
pvc.permittedArrowDirections = UIPopoverArrowDirectionRight
![](https://img.haomeiwen.com/i2571591/908e3c39e48a34f5.png)
pvc.permittedArrowDirections = UIPopoverArrowDirectionDown
![](https://img.haomeiwen.com/i2571591/cda3afd5c321dc1b.png)
pvc.permittedArrowDirections = UIPopoverArrowDirectionUp
![](https://img.haomeiwen.com/i2571591/4efd7f73701031c7.png)
通过以上打印发现,若要排除arrow在外,只需要将容器的frame设置为self.view.safeAreaLayoutGuide.layoutFrame即可
***begin-补充-begin***
![](https://img.haomeiwen.com/i2571591/fcfe045c348fca99.png)
使用约束(Masonry)进行布局,就利用mas_safeAreaGuide相关属性即可.
e.g.如前文的示例代码(上图)
// way 1
[self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view.mas_safeAreaLayoutGuide);
}];
// way 2
[self.bgView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_safeAreaLayoutGuideTop);
make.bottom.equalTo(self.view.mas_safeAreaLayoutGuideBottom);
make.leading.equalTo(self.view.mas_safeAreaLayoutGuideLeading);
make.trailing.equalTo(self.view.mas_safeAreaLayoutGuideTrailing);
}];
***end-补充-end***
OK~ 搞定
网友评论