UICollectionView高度不能使用UIScrollView内部动态递增

时间:2017-05-31 11:06:03

标签: ios swift scroll uiscrollview uicollectionview

我正在开发一款为用户展示照片的应用。我的设计就像Pinterest app。我在UICollectionView内添加了UIScrollView并禁用了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 App的行为。我想让我的应用像这个视频(https://youtu.be/Nm-sjXVEL5s

6 个答案:

答案 0 :(得分:4)

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

要显示scrollable header,您可以使用UICollectionReusableView作为section header的{​​{1}}。

1.UICollection视图代码:

collection view

<强> 2。接口

enter image description here

第3。输出屏幕:

enter image description here

修改

https://www.raywenderlich.com/107439/uicollectionview-custom-layout-tutorial-pinterest

中提供的代码中

进行一些更改:

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
    }
}

同样在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 } }

enter image description here

enter image description here

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

我开发了相同类型的应用,您正在尝试。为此我参加了Ray Wenderlich教程。

这是我的回购链接。

https://github.com/mvpVaibhav/Pixabay

答案 3 :(得分:0)

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

我观看了Pinterest应用,但没有在那里找到任何标题。 你需要什么样的自定义标题? 它应该有什么行为? 你需要几个部分的粘性标题,还是它应该与细胞一起消失?

看一下本教程 https://www.objc.io/issues/3-views/collection-view-layouts/

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

答案 4 :(得分:0)

不要使用图片查看侧边集合视图,只需使用 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")
  }
}

我正在向你展示这个故事板的形象 Your stroyboard should look like this

您的标题类应如下所示

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

答案 5 :(得分:0)

对于您的信息,UICollectionView已经是UIScrollView的子类。无需再次将其添加到UIScrollView。

以下是层次结构:

<强> UICollectionView-&GT; UIScrollView-&GT; UIView-&GT; UIResponder-&GT; NSObjec吨