Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UICollectionView height not dynamically incrementable using inside UIScrollView

I'm developing an app that show photos for users. My design was like Pinterest app. I added UICollectionView inside UIScrollView and disabled UICollectionView's scroll. But when I use this components like this UICollectionView not scrollable acording to its content. Only visible are showing and other are is not showing. The main pain in this project is CollectionViews' contents are dynamic. It could change with user interacyion. And my question is how to fully scroll UICollectionView with its dynamic content using with UIScrollView.

Let me share screenshots.

First image describes first open. Second image describes scrolling issue. Third image describes my storyboard.

Thanks for helpings.

Here is my storyBoard

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 think I couldn't clearly explain my issue. here I'll provide some additional videos to be clearly tell about the issue. I've upload 2 videos.

In this video my header is not scrolling with collectionview childs. So I want to scroll whole elements in screen. (https://youtu.be/0ArQe6mZytc)

In this short video you can see Pinterest App behaviour when scroll. I would like to make my app like this video (https://youtu.be/Nm-sjXVEL5s)

like image 299
salih Avatar asked May 31 '17 11:05

salih


1 Answers

For your requirement, there is no need to use UIScrollView. You can create the screen just using a UICollectionView.

To show a scrollable header, you can use UICollectionReusableView as the section header of the collection view.

1.UICollection view 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 in : 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

like image 125
PGDev Avatar answered Sep 28 '22 06:09

PGDev