【问题标题】:UICollectionView height not dynamically incrementable using inside UIScrollViewUICollectionView 高度不能在 UIScrollView 内动态增加
【发布时间】:2017-11-01 03:50:33
【问题描述】:

我正在开发一个为用户显示照片的应用。我的设计就像 Pinterest 应用程序。我在UIScrollView 中添加了UICollectionView 并禁用了UICollectionView 的滚动。但是当我使用像 UICollectionView 这样的组件时,根据它的内容不能滚动。只有可见的显示,其他的不显示。这个项目的主要痛点是 CollectionViews 的内容是动态的。它可能会随着用户交互而改变。我的问题是如何使用 UIScrollView 完全滚动 UICollectionView 及其动态内容。

让我分享截图。

第一张图片描述了第一次打开。第二张图片描述了滚动问题。 第三张图片描述了我的故事板。

感谢您的帮助。

这是我的故事板

还有我的代码

//
//  ViewController.swift
//  ScrollCollectionView
//
//  Created by Cbs on 31.05.2017.
//  Copyright © 2017 Cbs. All rights reserved.
//

import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 25
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
        cell.addShadow(opacitiy: 1, shadowRadius: 3, shadowOffsetWidth: 2, shadowOffsetHeight: 2, shadowColor: UIColor.lightGray, backgroundColor: UIColor.red)
        cell.addCornerRadius(cornerRadius: 8)
        return cell

    }
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let cellSpacing = CGFloat(2) //Define the space between each cell
        let leftRightMargin = CGFloat(40) //If defined in Interface Builder for "Section Insets"
        let numColumns = CGFloat(2) //The total number of columns you want

        let totalCellSpace = cellSpacing * (numColumns - 1)
        let screenWidth = UIScreen.main.bounds.width
        let width = (screenWidth - leftRightMargin - totalCellSpace) / numColumns
        let height = CGFloat(210) //whatever height you want

        return CGSize(width: width, height: height) // width & height are the same to make a square cell
    }

}

编辑:

我想我无法清楚地解释我的问题。在这里,我将提供一些额外的视频来清楚地说明这个问题。我上传了2个视频。

在此视频中,我的标题没有与 collectionview 子项一起滚动。所以我想滚动屏幕中的整个元素。 (https://youtu.be/0ArQe6mZytc)

在这个短视频中,您可以看到滚动时 Pinterest 应用程序的行为。我想让我的应用像这个视频一样 (https://youtu.be/Nm-sjXVEL5s)

【问题讨论】:

  • 为什么在滚动视图集合视图中添加集合视图是滚动视图本身的子类。
  • 我的建议是不要在 UIScrollView 中包含 UICollectionView,因为 UICollectionView 已经是 UIScrollView 的子类。使用 CollectionView 标头在顶部添加您的图像和标签。
  • @Imad 但我必须为我的功能使用自定义标头。使用自定义布局标题部分时消失了:S
  • @salih 集合视图具有补充标题视图功能。
  • @salih 看看这个为你的集合视图实现一个标题:stackoverflow.com/questions/21731318/…

标签: ios swift scroll uiscrollview uicollectionview


【解决方案1】:

供您参考,UICollectionView 已经是 UIScrollView 的子类。 UIScrollView 不需要再添加了。

以下是层次结构:

UICollectionView->UIScrollView->UIView->UIResponder->NSObjec‌​t

【讨论】:

    【解决方案2】:

    根据您的要求,无需使用UIScrollView。您可以只使用UICollectionView 创建屏幕。

    要显示scrollable header,您可以使用UICollectionReusableView 作为collection viewsection header

    1.UICollection查看代码:

    import UIKit
    
    class PinterestViewController: UIViewController
    {
        override func viewDidLoad()
        {
            super.viewDidLoad()
        }
    }
    
    extension PinterestViewController : UICollectionViewDataSource, UICollectionViewDelegate
    {
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
        {
            return 25
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
        {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
            return cell
        }
    
        func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
        {
            if kind == UICollectionElementKindSectionHeader
            {
                let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "headerView", for: indexPath)
                return headerView
            }
            return UICollectionReusableView()
        }
    }
    
    extension PinterestViewController : UICollectionViewDelegateFlowLayout
    {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
        {
            let cellSpacing = CGFloat(2) //Define the space between each cell
            let leftRightMargin = CGFloat(40) //If defined in Interface Builder for "Section Insets"
            let numColumns = CGFloat(2) //The total number of columns you want
    
            let totalCellSpace = cellSpacing * (numColumns - 1)
            let screenWidth = UIScreen.main.bounds.width
            let width = (screenWidth - leftRightMargin - totalCellSpace) / numColumns
            let height = CGFloat(210) //whatever height you want
    
            return CGSize(width: width, height: height) // width & height are the same to make a square cell
        }
    }
    

    2。界面:

    3.输出画面:

    编辑:

    在提供的代码中:https://www.raywenderlich.com/107439/uicollectionview-custom-layout-tutorial-pinterest

    进行一些更改:

    class PinterestLayout: UICollectionViewFlowLayout
    {
        //...
    
        override func prepare()
        {
            // 1
            if cache.isEmpty
            {
                //...
                var yOffset = [CGFloat](repeating: 150, count: numberOfColumns) //Height of your header view
                //...
            }
        }
    
        override var collectionViewContentSize: CGSize
        {
            return CGSize(width: contentWidth, height: contentHeight)
        }
    
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
        {
            guard let attributes = super.layoutAttributesForElements(in: rect) else
            {
                return nil
            }
            var layoutAttributes = [UICollectionViewLayoutAttributes]()
            for attr in attributes where attr.representedElementKind == UICollectionElementKindSectionHeader
            {
                if let supplementaryAttributes = layoutAttributesForSupplementaryView(ofKind: UICollectionElementKindSectionHeader, at: attr.indexPath)
                {
                    layoutAttributes.append(supplementaryAttributes)
                }
            }
            for attributes in cache
            {
                if attributes.frame.intersects(rect)
                {
                    layoutAttributes.append(attributes)
                }
            }
            return layoutAttributes
        }
    
        override func layoutAttributesForSupplementaryView(ofKind elementKind: String, at indexPath: IndexPath) -> UICollectionViewLayoutAttributes?
        {
            if elementKind == UICollectionElementKindSectionHeader
            {
                let attributes = UICollectionViewLayoutAttributes(forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, with: indexPath)
                attributes.frame = CGRect(x: 0, y: 0, width: self.contentWidth, height: 150) //Height of your header view
                return attributes
            }
            return nil
        }
    }
    

    也在Collection View Interface:

    【讨论】:

    • 您的方法工作正常。但我希望单元格视图像上传的 youtube 上的 pinterest youtube.com/watch?v=0ArQe6mZytc&feature=youtu.be
    • 像 pinterest 这样的子视图意味着什么?你到底想要什么?
    • 我的意思是collectionview拥有的单元格。单元格的大小可以根据其内容进行更改
    • 您需要为此制作自定义集合视图布局。参考:raywenderlich.com/107439/…。此链接提供了您想要的内容。
    • 我制作了这个布局,但自定义布局不适用于 uicollectionreusableview
    【解决方案3】:

    不要在侧面集合视图中使用图像视图,您可以简单地使用 UICollectionReusableView 作为标题

    将此添加到您的课程中

    override func collectionView(_ collectionView: UICollectionView,
                                 viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
      //1
      switch kind {
      //2
      case UICollectionElementKindSectionHeader:
        //3
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "customHeaderView", for: indexPath) as! customHeaderView
        headerView.imageView.image = //some random image local or dynamic you can use here..
        return headerView
      default:
        //4
        assert(false, "Unexpected element kind")
      }
    }
    

    查看我正在向您展示的故事板图片

    您的标头类应如下所示

    class customHeaderView: UICollectionReusableView {
      @IBOutlet weak var imageView: UIImageView!
      //you can add more functions here you want
    }
    

    【讨论】:

      【解决方案4】:

      您的解决方案似乎打破了 CollectionView 的主要目的 - 节省应用内存并重用设备资源。但是在这里你试图让 CollectionView 的高度大于设备大小,这是不好的。 如果你有 1000 张图像怎么办?您的应用程序将因内存不足问题而崩溃。 将自定义单元格和标题与 collectionviewflowlayout 子类一起使用。 例如,看看这个示例代码。 https://github.com/zwaldowski/AdvancedCollectionView

      我看过 Pinterest 应用程序,但没有找到任何标题。 您需要什么样的自定义标题? 它应该有什么行为? 您需要几个部分的粘性标题还是应该与单元格一起消失?

      看看这个教程 https://www.objc.io/issues/3-views/collection-view-layouts/

      您的应用的部署目标是什么?如果是 iOS 9,如果需要,则 UICollectionViewFlowLayout sectionHeadersPinToVisibleBounds 属性。

      【讨论】:

      • 您好,我已经使用提供的 youtube 链接编辑了我的问题。你能看看问题吗?
      【解决方案5】:

      我开发了相同类型的应用程序,您正在尝试这样做。为此,我遵循了Ray Wenderlich 教程。

      这是我的回购链接。

      https://github.com/mvpVaibhav/Pixabay

      【讨论】:

      • 您好@Vaibhav,您的回答很好,但我们尝试了一些方法也可以。我们也希望标题可以通过 pinterest 布局滚动。我用一张图片解释我的情况。 i.stack.imgur.com/D8mOI.png
      • 很容易实现。只需放置 UICollectionView 并启用水平滚动即可。无需将 UICollectionView 放在 UIScrollView 中
      • 我只想要垂直滚动。当我滚动标题时应该已经消失了。
      • 尝试在标题部分视图中添加集合视图。
      • 我尝试添加标题部分视图,但它不适用于自定义布局。
      【解决方案6】:

      将 NSLayoutConstraint 作为集合视图的高度,并在 viewdidLayoutSubviews() 方法中更改该高度约束,如下所示。 self.hgtCollectionView.constant = CGFloat(number of rows) * 210) + CGFloat(10)

      这将根据其内容更新集合视图的高度。

      【讨论】:

      • 您是否将滚动视图内容大小设置为集合视图高度?
      • 显示你更新的代码。所以我可以给你一些建议。
      • self.constant.constant = CGFloat(2) * 410 + CGFloat(10) 你只能看到 4 行。
      • self.constant.constant = CGFloat(行数) * 单元格高度 + CGFloat(单元格间距)
      • 但是你的项目数是 25 所以行数是 12 。你的方程应该是,self.constant.constant = CGFloat(12) * 210 + CGFloat(10)
      猜你喜欢
      • 2019-10-12
      • 1970-01-01
      • 1970-01-01
      • 2014-07-30
      • 1970-01-01
      • 2019-06-15
      • 1970-01-01
      • 2019-07-30
      • 2013-04-28
      相关资源
      最近更新 更多