【问题标题】:UICollectionView in landscape on iPhone XiPhone X 上的横向 UICollectionView
【发布时间】:2017-09-16 21:09:04
【问题描述】:

当 iPhone X 横向使用时,您应该检查 safeAreaInsets 以在左侧和右侧制作适当大的排水沟。 UITableView 具有新的insetsContentViewsToSafeArea 属性(默认为 true),可以自动将单元格内容保存在安全区域中。

我很惊讶 UICollectionView 似乎没有类似的东西。我希望对于垂直滚动的集合视图,在横向时,左侧和右侧将插入到安全区域(相反,如果需要纵向,水平滚动的集合视图将被插入)。

确保这种行为的最简单方法似乎是添加到集合视图控制器中:

- (void)viewSafeAreaInsetsDidChange {
    [super viewSafeAreaInsetsDidChange];
    UIEdgeInsets contentInset = self.collectionView.contentInset;
    contentInset.left = self.view.safeAreaInsets.left;
    contentInset.right = self.view.safeAreaInsets.right;
    self.collectionView.contentInset = contentInset;
}

...假设 contentInset.left/right 通常为零。

(注意:是的,对于 UICollectionViewController,它必须是 self.view.safeAreaInsets;在调用它时,对 safeAreaInsets 的更改奇怪地尚未传播到 self.collectionView

我错过了什么吗?该样板文件很简单,但现在对于接触屏幕边缘的每个 集合视图来说,它实际上是必需的。 Apple 没有提供默认启用此功能的功能,这似乎真的很奇怪。

【问题讨论】:

  • 请注意,建议不要插入整个集合视图内容。例如,节标题应该从边缘延伸到边缘。这是使用布局上的部分插图而不是集合视图上的内容插图来完成的。
  • 啊,是的,很好。我最初的测试设置是一个没有标题的单节,所以我没有考虑这个。
  • @Joey 为什么不应该将节标题插入到安全区域?部分标题中的文本被横向的缺口隐藏。
  • @Jonny header 的内容应该被正确插入,但是 header view 本身不应该被插入,从而允许它的背景从边到边拉伸。
  • @Joey 好的,我的内容插入不正确,我必须仔细检查。

标签: ios uicollectionview uikit ios11 iphone-x


【解决方案1】:

有同样的问题。这对我有用:

override func viewDidLoad() {
    if #available(iOS 11.0, *) {
        collectionView?.contentInsetAdjustmentBehavior = .always
    }
}

.always 枚举案例的 documentation 表示:

始终在内容调整中包含安全区域插图。

此解决方案在手机旋转的情况下也能正常工作。

【讨论】:

  • @Jonny 这个解决方案比我接受的答案更好,因为如果手机旋转它也能按预期工作。
  • 是的,我现在也最终使用了它。这很好,因为可以在 viewDidLoad 中设置设置,作为一次性解决方案感觉更方便。
  • 这对我有用,但是当我以横向的集合视图进入 VC 时,它会将所有单元格向左对齐,我需要旋转到纵向并返回。尝试使布局无效等,但没有任何效果。你遇到过这样的行为吗?
  • @ŁukaszPrzytuła 不,我不会遇到这种情况。您在设置collectionView?.contentInsetAdjustmentBehavior = .always 时是否体验过它并按预期工作?
  • 已经设法修复它。发现一些滚动到底部的代码,将 x 硬编码的 contentOffset 更改为 0。
【解决方案2】:

虽然 Nathan 关于 UICollectionView 与各种布局的多功能性是正确的,但我主要关心的是使用 UICollectionViewFlowLayout 的“默认”情况。

原来,iOS 11 为 UICollectionViewFlowLayout 添加了一个 sectionInsetReference 属性。它上面的official documentation 目前缺少描述,但是标题将其描述为

节插入的参考边界将被定义为相对于。默认为.fromContentInset

注意:将始终至少尊重内容插图。例如,如果sectionInsetReference 等于.fromSafeArea,但调整后的inset 大于安全区域和section inset 的组合,则section 内容将与content inset 对齐。

可能的值是

@available(iOS 11.0, *)
public enum UICollectionViewFlowLayoutSectionInsetReference : Int {
    case fromContentInset
    case fromSafeArea
    case fromLayoutMargins
}

并将其设置为 .fromSafeArea 会产生所需的结果,即最初处于纵向时:

然后当旋转到横向时,单元格会被插入,以使它们完全在安全区域内:

...但是,目前存在一个错误,当视图旋转回纵向时, 视图一直处于横向状态,它继续表现得好像左/右 safeAreaInsets 设置为横向价值观:

我已就此问题提交了一份雷达 (rdar://34491993)。

【讨论】:

  • 很棒的发现。我很惊讶没有更多的人遇到这个问题。但是,我无法重现您提到的错误。当我在横向后旋转回纵向时,我的插图是正确的。
  • 嗯,有趣。我用于截图的测试项目(并与我的错误报告一起提交)非常小,我认为这将反映最基本的默认行为......我还没有收到 Apple 的回复。 iPhone X 模拟器肯定还有很多其他错误行为......无论如何,我希望在 iPhone X 实际发布时,我们将拥有 iOS 11.1,并希望这些问题能够得到修复。
  • @WesCampaigne,你能更新你的答案吗?图片链接已失效。
  • 图片还在为我工作?它们使用堆栈溢出的集成图像内容托管。
  • 你是如何让你的标题拥有全宽背景的?
【解决方案3】:

感谢上面的帮助。对于我的 UICollectionViewController 子类,我在 viewDidLoad() (Swift 3) 中添加了以下内容:

if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
    if #available(iOS 11.0, *) {
        flowLayout.sectionInsetReference = .fromSafeArea
    }
}

【讨论】:

    【解决方案4】:

    请记住,上述解决方案不能解决您的集合单元格视图(以及受限于其单元格的前缘或后缘的子视图)对于集合视图边界是全宽并且未设置为服从的情况

    strong>安全区域布局指南。

    注意:@petrsyn 的答案使标题从侧面插入,这是大多数人可能不想要的,@Wes Campaigne 的答案对于全角单元格实际上并不能正常工作,其中子视图附加到单元格的前缘或后缘。

    必须将 Xib 和 Storyboard 文件设置为使用安全区域布局指南,然后使用自动布局来放置与安全区域相关的约束或执行代码类似。

    【讨论】:

      【解决方案5】:

      UICollectionView 旨在灵活用于各种布局。最常见的布局是具有多行和多列的网格,但也可以使用 UICollectionView 创建非网格布局。

      另一方面,UITableView 专为全角单元格设计。

      因此,UITableView 将内置对处理安全区域插入的支持是有道理的,因为表格视图布局总是会受到它的影响。因为UICollectionView 使用自定义布局,所以在每个实现的基础上解决这些问题而不是试图提供一种万能的解决方案是有意义的。

      【讨论】:

        【解决方案6】:

        如果您以编程方式将集合视图添加为主视图的子视图 - 那么您可以在 viewDidLoad 方法中执行此操作:

        collectionView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(collectionView)
        
        NSLayoutConstraint.activate([
                collectionView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
                collectionView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
                collectionView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
                collectionView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor)
        ])
        

        【讨论】:

        • 为什么基里尔的回答被否决了?有什么陷阱吗?就我而言,他的回答帮助我意识到,我可以将已经在 viewDidLoad 中的 collectionView 限制到安全区域(而不是在 UICollectionViewCell 中)。这解决了我的问题,尽管我的问题与线程启动器问题有点不同。除非有人可以向我展示他的答案存在的问题,否则我会支持 Kirills 的回答。
        • @andreas1724 他的解决方案的问题是集合视图被裁剪到安全区域。集合视图内容应该能够滚动越过安全区域并进入视图边界(包含屏幕上所有像素的矩形)。正确的方法是插入内容。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-31
        • 2012-04-23
        相关资源
        最近更新 更多