UICollectionView height not dynamically increasing using UIScrollView inside

I am developing an application that displays photos to users. My design was similar to the Pinterest app. I added UICollectionView

inside UIScrollView

and disabled scrolling UICollectionView

. But when I use components like this UICollectionView not scrollable on content. Only visible are displayed, others are not displayed. The main problem in this project is the content of the CollectionViews is dynamic. This can change with user enthusiasm. And my question is how to completely scroll the UICollectionView with its dynamic content using the UIScrollView.

Let me share screenshots.

The first image describes the first open. The second image describes the scrolling problem. The third image describes my storyboard.

Thanks for the help.

dYQwo.jpg0RXaB.png

Here is my story

UWTFQ.png

And my code

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

}

      

EDIT:

I guess I couldn't clearly explain my problem. here I will provide some additional videos to clearly explain the problem. I have uploaded 2 videos.

In this video, my title is not scrolling with the children of the collection. So I want to scroll through whole items on the screen. ( https://youtu.be/0ArQe6mZytc )

In this short video you can see the scrolling behavior of the Pinterest app. I would like to make my application like this video ( https://youtu.be/Nm-sjXVEL5s )

+3


source to share


6 answers


There is no need to use for your requirement UIScrollView

. You can create a screen with UICollectionView

.

To show a scrollable header

, you can use UICollectionReusableView

both section header

for collection view

.

1.UICollection display code:

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. Interface:

enter image description here

3. Output screen:

enter image description here



Edit:

In the code provided at: https://www.raywenderlich.com/107439/uicollectionview-custom-layout-tutorial-pinterest

Make some changes:

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

      

Also in Collection View Interface

:

enter image description here

enter image description here

+2


source


Take NSLayoutConstraint for collection view height and change height constraint in viewdidLayoutSubviews () method as shown below. self.hgtCollectionView.constant = CGFloat(number of rows) * 210) + CGFloat(10)



This will update the height of the collection view to match its contents.

+1


source


I have developed the same application that you are trying to do. I followed Ray Wenderlich for this.

Here is the link for my repo.

https://github.com/mvpVaibhav/Pixabay

+1


source


It looks like your solution just breaks the main purpose of CollectionView - to save application memory and reuse device resources. But here you are triyng to increase the height of the CollectionView than the size of the device, which is bad. What if you have 1000 images? your application will just crash due to a memory issue. Use custom cells and headers with a subclass of collectionviewflowlayout. Have a look at this sample code for example. https://github.com/zwaldowski/AdvancedCollectionView

I looked at the Pinterest app but couldn't find any titles. What custom header do you need? What behavior should this have? Do you need a sticky header for multiple sections, or should it go away with cells?

take a look at this tutorial https://www.objc.io/issues/3-views/collection-view-layouts/

What is the purpose of deploying your application? if iOS 9 then UICollectionViewFlowLayout sectionHeadersPinToVisibleBounds if you need it.

0


source


Don't use side view to view images, you can just use UICollectionReusableView for your title

Add this to your class

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

      

The check is the storyboard image I show you Your panel should look like this

The header class should look like this:

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

      

0


source


For your information, UICollectionView is already a subclass of UIScrollView. There is no need to add it again to the UIScrollView.

Below is the hierarchy:

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

0


source







All Articles