UICollectionViewCell - 针对不同大小类

时间:2016-03-05 02:52:24

标签: ios autolayout uicollectionview uicollectionviewcell size-classes

我有一个简单的UICollectionViewCell,其中包含一张图片和一张标签。在常规常规尺寸类中,我希望图像位于顶部,并且标签位于其下方。这就是Xcode的预览标签中的样子:

enter image description here

在任何其他尺寸类中,我希望图像位于左侧,标签位于右侧:

enter image description here

我以这种方式设置约束:

ImageView具有以下约束:

  • Any-Any的领先和最高限制
  • Any-Any的固定宽度和高度

标签有以下限制:

  • 追踪约束到Superview - for Any-Any
  • 对ImageView的顶级约束 - 仅适用于Regular-Regular
  • 超级视图的主要约束 - 仅适用于常规定期
  • 对Superview的最高约束 - 对于Any-Any而不是对于Regular-Regular
  • 对ImageView的主要约束 - 适用于Any-Any但不适用于Regular-Regular

我还实现了根据当前特征集合返回不同单元格大小的方法:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
    if (traitCollection.horizontalSizeClass == .Regular) {
      return CGSizeMake(240, 194)
    }
    else {
      return CGSizeMake(340, 128)
    }
  }

预览中的单元格看起来很好,当我在iPhone上运行时(例如Compact-Regular),一切正常。但是,当我在iPad上运行时,自动布局会中断:

enter image description here

当然,我在调试控制台中收到了一些警告:无法同时满足约束条件。

所以,我想问题是 - 为不同大小的类设置单元格的正确方法是什么?

我用demo project

创建了一个github仓库

谢谢!

2 个答案:

答案 0 :(得分:2)

您要做的是像您一样禁用常规 - 常规尺寸类的约束,但也将其优先级更改为< 1000(即不要求)。这样,它将使用特定大小类的更高优先级约束。

enter image description here

答案 1 :(得分:1)

这可能不是最优雅的解决方案,但我过去尝试这样做会导致Autolayout大小类更加痛苦,我发现最好的解决方案是:

  1. 为每个尺寸类设置一个单独的笔尖,然后根据需要在每个尺寸类中布局视图。
  2. 为每个尺寸类分别设置CollectionViewFlowLayouts,然后在尺寸更改时在它们之间进行转换。
  3. 遵循此模式,单元格大小将由collectionViewFlowlayout而不是sizeForItem...确定,您可以更好地控制其他参数,例如sectionInsetminimumLineSpacing等。在集合视图中更改大小类时通常需要改变。

    以下代码更改对我有用:

      let cellIdentifierCompact = "CustomCellCompact"
      let cellIdentifierRegular = "CustomCellReg"
    
      lazy var compactLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSizeMake(240, 194)
        return layout
      }()
    
    lazy var regLayout: UICollectionViewFlowLayout = {
        let layout = UICollectionViewFlowLayout()
        layout.itemSize = CGSizeMake(320, 128)
        return layout
      }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        let customCellNib = UINib(nibName: cellIdentifierCompact, bundle: nil)
        self.collectionView.registerNib(customCellNib, forCellWithReuseIdentifier: cellIdentifierCompact)
    
        let customCellNibReg = UINib(nibName: cellIdentifierRegular, bundle: nil)
        self.collectionView.registerNib(customCellNibReg, forCellWithReuseIdentifier: cellIdentifierRegular)
        self.configureLayoutForSize()
      }
    
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cellId = self.collectionView.collectionViewLayout == self.regLayout ? cellIdentifierRegular : cellIdentifierCompact
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId, forIndexPath: indexPath)
        return cell
      }
    
      func configureLayoutForSize(){
        switch self.traitCollection.horizontalSizeClass{
        case UIUserInterfaceSizeClass.Regular:
          self.collectionView.setCollectionViewLayout(self.regLayout, animated: false)
        case .Compact, .Unspecified:
          self.collectionView.setCollectionViewLayout(self.compactLayout, animated: false)
        }
      }
    
      override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
        self.configureLayoutForSize()
        self.collectionView.reloadData()
      }