Instagram / IGListKit

A data-driven UICollectionView framework for building fast and flexible lists.
https://instagram.github.io/IGListKit/
MIT License
12.87k stars 1.54k forks source link

Two Section Controllers in One but scroll all the screen #469

Closed kwstasna closed 7 years ago

kwstasna commented 7 years ago

New issue checklist

General information

So i have 2 section controllers

class WeekendSectionController: IGListSectionController {
    var event: Event! = nil
    let loader = EventLoader()
    override init() {
        super.init()
        inset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 15)
    }

}

extension WeekendSectionController: IGListSectionType {
    func numberOfItems() -> Int {
        return 1
    }

    func sizeForItem(at index: Int) -> CGSize {
      return CGSize(width: 242, height: 151)
    }

    func cellForItem(at index: Int) -> UICollectionViewCell {
        let cell = collectionContext!.dequeueReusableCell(withNibName: "WeekendCollectionViewCell", bundle: nil, for: self, at: index)
        if let cell = cell as? WeekendCollectionViewCell {
            cell.configureWeekendCell(events: event)
        }
        return cell
    }

    func didUpdate(to object: Any) {
        event = object as? Event
    }

    func didSelectItem(at index: Int) {
        print(index)
        print(event.eventName)
    }
}

This shows horizontal scrolling cells.

And this section

class NormalSectionController: IGListSectionController {

    var event: Event! = nil

    override init() {
        super.init()
        inset = UIEdgeInsets(top: 0, left: 0, bottom: 15, right: 0)
    }
}

extension NormalSectionController: IGListSectionType {
    func numberOfItems() -> Int {
        return 2
    }

    func sizeForItem(at index: Int) -> CGSize {

        if index == 0 {
            return CGSize(width: 320, height: 150)
        } else {
            return CGSize(width: 320, height: 90)
        }
    }

    func cellForItem(at index: Int) -> UICollectionViewCell {
        if index == 0 {
            let cell1 = collectionContext!.dequeueReusableCell(withNibName: "NormalCollectionViewCell", bundle: nil, for: self, at: index)
            if let cell = cell1 as? NormalCollectionViewCell {
                cell.configureImageCell(events: event)
            }
            return cell1
        } else {
            let cell2 = collectionContext!.dequeueReusableCell(withNibName: "InfoNormalCollectionViewCell", bundle: nil, for: self, at: index)
          if let cell = cell2 as? InfoNormalCollectionViewCell {
                cell.configureInformationCell(events: event)
            }
             return cell2
        }
    }

    func didUpdate(to object: Any) {
        event = object as? Event
    }

    func didSelectItem(at index: Int) {
        print(index)
        print(event.eventName)
    }

}

This is vertical scrolling cells.

In my ViewController, i would like the user to scroll vertically to the hole view but with this VC that i created, the user can scroll ONLY at the 2nd section.

class LocationViewController: UIViewController {
    let loader = EventLoader()
    let screenSize: CGRect = UIScreen.main.bounds
   let collectionView: IGListCollectionView = {
        let view = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout())
        view.backgroundColor = UIColor.black
        return view
    }()
    lazy var adapter: IGListAdapter = {
        return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
    }()
    let weekendCollectionView: IGListCollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        let view = IGListCollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        view.alwaysBounceVertical = false
        view.alwaysBounceHorizontal = true
        return view
    }()
    lazy var weekendAdapter: IGListAdapter = {
        return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        loader.loadEvents{
            self.adapter.performUpdates(animated: true)
            self.weekendAdapter.performUpdates(animated: true)
        }
        adapter.collectionView = collectionView
        weekendAdapter.collectionView = weekendCollectionView
        adapter.dataSource = self
        weekendAdapter.dataSource = self
        setupUI()
    }

   func setupUI() {
        let navigationBarHeight: CGFloat = self.navigationController!.navigationBar.frame.height
        weekendCollectionView.frame = CGRect(x: 0, y: navigationBarHeight, width: screenSize.width, height: 210)
        weekendCollectionView.backgroundColor = .red
        collectionView.frame = CGRect(x: 0, y: navigationBarHeight + 210, width: screenSize.width, height: screenSize.height * 0.7)
        view.addSubview(weekendCollectionView)
        view.addSubview(collectionView)
    }
}
// MARK: - IGListAdapterDataSource
extension LocationViewController: IGListAdapterDataSource {
    func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
        if listAdapter == weekendAdapter {
            let items: [IGListDiffable] = loader.entries as [IGListDiffable]
            return items
        } else {
            let items: [IGListDiffable] = loader.entries as [IGListDiffable]
            return items
        }
    }
    func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
        if listAdapter == weekendAdapter {
            return WeekendSectionController()
        } else {
            return NormalSectionController()
        }
    } 
    func emptyView(for listAdapter: IGListAdapter) -> UIView? { return nil }
}

So what i'm trying to make is exactly as Instagram works.

I've tried to add a scrollview to the view but didn't work out well at all. Is there any suggestion of how to combine 2 sections in one vertical scrolling collection view?

kwstasna commented 7 years ago

Ok as i understand by searching previous issues, there is this

https://github.com/Instagram/IGListKit/issues/31

and

https://github.com/Instagram/IGListKit/milestone/3

So is this gonna be a feature in 3.0.0 ? @rnystrom

rnystrom commented 7 years ago

Hey @kwstasna sorry I didn't come back to this. Yup! We're planning on making nested lists a lot easier w/ a base class that handles a lot of the common setup for you in 3.0.0. We haven't started on this yet, but we will definitely get to it!

Have you taken a look at our example of nested adapters?

kwstasna commented 7 years ago

Yes I'm trying to make it work but it seems that i'm doing something wrong but i can't figure out what.

So i have 3 section controllers. 1) For the vertical collection view. (NormalSectionController) 2) For the horizontal items (WeekendSectionController) 3) The section controller that contains the items from (2) i think here is the issue (HorizontalSectionController)

I've uploaded a demo project here

https://www.dropbox.com/s/5i6w2878296tsfo/ig-event%202.zip?dl=0

If you have the time to take a look at the 3rd section controller in the func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] I don't know exactly what should i return because in your example you return some Int from 0 to the number that is in data.

The expected result from my code is to have the first Section of the collection view a height of 170px and horizontal scrolling and second Section to have vertical scrolling.

The demo result show's a large white section with no items and after the white section, there is the second section normal as it has to be.

Thanks a lot for your time and for your contribution. To be honest even with the second section only i've seen a drop of the memmory usage than my tableview that i hade before.

Really nice work :smile:

kwstasna commented 7 years ago

Nevermind. I followed up those 2 brilliant tutorials from @kzin

1st post https://medium.com/cocoaacademymag/iglistkit-migrating-an-uitableview-to-iglistkitcollectionview-65a30cf9bac9#.cm9mgee4y

And on the 2nd post https://medium.com/cocoaacademymag/how-to-improve-your-iglistcollectionview-e13afe06dfeb#.96jco89om

He explains how to do it.

Although it took me some hours, hope on your next update you will make things a bit easier for the beginners :heart:

rubera commented 7 years ago

Hi @kwstasna. Is that possible to take a look at the solution you came to? I'm that beginner you've mentioned above ) Fighting days already with the same task.