collectionview with the horizontal scroll with mulitple section

前端 未结 2 1367
予麋鹿
予麋鹿 2020-12-08 05:54

I want to develop the screen(objective C) like this :

In this there are section names :

  1. New Games we Love
  2. New Apps We Love

Bo

相关标签:
2条回答
  • 2020-12-08 06:23

    What you are trying to do is not that difficult. I have created a prototype of what you are looking at. This is how your storyboard's view controller and its document outline look like:

    Here's the code for each component

    TableViewController

    class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Do any additional setup after loading the view.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return 5
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! MyTableViewCell
    
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 160
    }
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return (section%2 == 0) ? "Games we love" : "Apps we love"
    }
    }
    

    MyTableViewCell

    class MyTableViewCell: UITableViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    let imageNames = ["candy_crush", "cut_the_ropes", "game_1", "little_pet_shop", "zuba"]
    let gameNames  = ["Candy Crush", "Cut the Ropes", "Arbitrary Game 1", "Littlest Pet Shop", "Zuba"]
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    
        // Configure the view for the selected state
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imageNames.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! MyCollectionViewCell
        cell.imageView.image  = UIImage.init(named: imageNames[indexPath.row])
        cell.titleLabel.text  = gameNames[indexPath.row]
        cell.detailLabel.text = "Games"
    
        return cell
    }
    }
    

    MyCollectionViewCell

    class MyCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var detailLabel: UILabel!
    }
    

    This is how it looks like on the simulator

    0 讨论(0)
  • 2020-12-08 06:26

    Workaround (Using UICollectionView with Swift 4)

    I am facing the same issue and can't find a way to make it work with UICollectionViewFlowLayout.

    If you want to use UICollectionView, but the SupplementaryView is not flexible enough, you can do this workaround:

    I have a fixed UILabel in the top-left side of the CollectionView and one floating UILabel that will move to the right accordingly. If there is only one section visible the second label will be hidden

    We can intercept all cells being created/dequeued in the collectionView:cellForItemAt indexPath: method, but will will give you a lot of cell frames (many of them being prepared but still offscreen, and you will have to manage what frame corresponds to what section. This can be tricky if you have multiple rows in your horizontal scrolling collection view

    You need to intercept the sections and the cell frames to found the lowest x coordinate, and the most reliable way is to inspect the .visibleCells property of the collectionView. This may be a lot of iterations (depending on the number of visible cells) and I'd love to identify a more efficient way. (a delegate method, a CollectionViewCellsDidAppear kind of notification, or being able to add an Observer to the .visibleCells property (not possible given that it is read-only)

    So far this works (Swift 4), but has room for improvement:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CellID", for: indexPath) as! GalleryCell
        cell.label?.text = String((itemsArrays[indexPath.section][indexPath.row]))
        var pointsDict = Dictionary<Int, CGFloat>()
        for item in collectionView.visibleCells {
            let point = item.convert(CGPoint.zero, to: self.superview)
            let section = collectionView.indexPath(for: item)!.section
            if pointsDict[section] != nil {
                if point.x < pointsDict[section]! {
                    pointsDict[section] = point.x
                }
            } else {
                pointsDict[section] = point.x
            }
        }
        updateLabels(dict: pointsDict)
        return cell
    }
    

    This code will give you a Dictionary with visible sections (keys) and the lowest x coordinate for each section (value) to align the floating label2 (my label1 has a fixed x at the left of the collectionView). You can also animate, hide/show the labels accordingly

    This workaround is not optimal and I will post additional information if a solution using UICollectionViewFlowLayout

    0 讨论(0)
提交回复
热议问题