繁体   English   中英

Swift:无法在 SplitViewController 中调整 collectionViewCells 的大小

[英]Swift: Unable to resize collectionViewCells in SplitViewController

我正在尝试调整SplitViewControllermasterViewController内的collectionView单元格,但调整大小不起作用。 我已经实现了必要的viewWillTransitioninvalidateLayout ,如果它没有放在splitViewController中,结果会很好。 就我而言,我有全屏单元格大小。

这是我的实现:

//This CollectionController is housed inside a TabBarController. 
//The TabBarController is the masterViewController
class CollectionController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

     lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.backgroundColor = .gray
        cv.dataSource = self
        cv.delegate = self
        layout.scrollDirection = .horizontal
        cv.isPagingEnabled = true
        cv.showsHorizontalScrollIndicator = false
        cv.showsVerticalScrollIndicator = false
        cv.contentInsetAdjustmentBehavior = .always
        cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
    }()

    var spacing: CGFloat = 16

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(collectionView)
        collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 3
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 16
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 16
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let layoutFrame = view.safeAreaLayoutGuide.layoutFrame
        let size = CGSize(width: layoutFrame.width, height: layoutFrame.height)
        print("SizeForItem", size)

        return setUpCellSize(size: size)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)

        if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            print("Transit1", size)

            layout.itemSize = setUpCellSize(size: size) //With or without this makes no difference
            layout.invalidateLayout()

            print("Transit2", size)

        }
    }

    func setUpCellSize(size: CGSize) -> CGSize {
        return size
    }
}

这是纯粹在TabBarController中实现的结果,即不在splitViewController中实现。 注意到单元格(蓝色)位于状态栏下方。 结果是预期和期望的。

在此处输入图像描述

这是在splitViewController中实现的结果。 注意到在第一次旋转到横向时,单元格位于状态栏上方。 当旋转回纵向时,单元格没有调整回全屏。

在此处输入图像描述

如果将collectionView 放在masterViewController 中,是否还有其他需要实现的东西?

编辑

我在sizeForItemviewWillTransition中添加了打印语句。 事实证明,在第二次旋转时, viewWillTransition中的新大小没有传递给sizeForItem

甚至对setupCellSize的显式调用也没有正确更新。 它还给出The behavior of the UICollectionViewFlowLayout is not defined警告。 见 gif(当 iPad 处于横向模式时,Gif 开始)。

另请注意,当 iPad 从横向 -> 纵向旋转时,蓝色单元格锚定到 statusBar 的底部和 tabBar 的顶部。 这是所希望的。 然后当从纵向 -> 横向旋转回来时,蓝色单元格超过状态栏并进入 tabBar 下方。 这不是我想要的。

在此处输入图像描述

您需要将CollectionController (主控制器)嵌入UINavigationController中。 如果您真的不想要导航栏,只需将其隐藏即可。

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    self.navigationController?.navigationBar.isHidden = true
}

在此处输入图像描述

好的,我已经设法解决了这个问题。 @Glenn 的解决方案有部分帮助。 帮助完全解决这个问题的部分来自这篇文章

首先,实施@Glenn 的解决方案,将CollectionController嵌入UINavigationController并隐藏导航栏(因为我不想要导航栏)。

其次,在viewWillLayoutSubviews中添加invalidateLayout

完整代码:

class CollectionController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

     lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal

        let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        cv.translatesAutoresizingMaskIntoConstraints = false
        cv.backgroundColor = .gray
        cv.dataSource = self
        cv.delegate = self
        cv.isPagingEnabled = true
        cv.alwaysBounceHorizontal = true
        cv.showsHorizontalScrollIndicator = false
        cv.showsVerticalScrollIndicator = false
        cv.contentInsetAdjustmentBehavior = .always
        cv.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
        return cv
    }()

    var spacing: CGFloat = 16

    //FIRST
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.navigationBar.isHidden = true
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(collectionView)
        collectionView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
        cell.backgroundColor = .blue
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let layoutFrame = view.safeAreaLayoutGuide.layoutFrame
        let size = CGSize(width: layoutFrame.width, height: layoutFrame.height)
        return setUpCellSize(size: size)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        collectionView.collectionViewLayout.invalidateLayout()
    }

    //SECOND
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()            
        collectionView.collectionViewLayout.invalidateLayout()
    }


    func setUpCellSize(size: CGSize) -> CGSize {
        return size
    }
}

结果就像这样,蓝色单元格很好地锚定在statusBar的底部和tabBar的顶部。 在此处输入图像描述

附带说明一下,我在这个线程中尝试了一些解决方案,但这些对我不起作用:

  • 按照此处的建议将shouldInvalidateLayoutForBoundsChange返回为true
  • 按照这里的建议UICollectionViewFlowLayout

如果有人决定在splitViewController中尝试解决相同情况的解决方案,请注意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM