Expandable UICollectionViewCell

后端 未结 3 874
囚心锁ツ
囚心锁ツ 2020-12-13 16:27

I\'m trying to program an expandable UICollectionViewCell. If the user presses the topbutton, the cell should expand to a different height and reveal the underlying content.

相关标签:
3条回答
  • 2020-12-13 17:02

    You can use header to show non-expand cell. And when you two a button or something in it , then you can insert other part (expanding part ) as a row in that section which the header belongs to.

    Benefits - you can use many provided animations when the expanding happen.

    0 讨论(0)
  • 2020-12-13 17:08

    Don't change the cell frame directly. Implement func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize and handle heights there.

    Lets say you have one cell in your collectionView and a top button above it:

    let expanded = false
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
    if expanded{
       // what is the size of the expanded cell?
       return collectionView.frame.size 
    }else{
        // what is the size of the collapsed cell?
       return CGSizeZero
    }
    }
    
    @IBAction func didTouchUpInsideTopButton(sender: AnyObject){
        // top button tap handler
        self.expanded = !self.expanded
        // this call will reload the cell and make it redraw (animated) Since the expanded flag changed, the sizeForItemAt call above will return a different size and animate the size change
        self.collectionView.reloadItemsAtIndexPaths([NSIndexPath(forRow: 0, inSection: 0)])
    }
    
    0 讨论(0)
  • 2020-12-13 17:18

    If you have more than cell that needs to be expanded to different height when a button is touched inside the collection view cell, then, here is the code.

    I have used the delegate pattern to let the controller know, button of which cell was touched using the indexPath. You need to pass the indexpath of the cell to the cell when creating the cell.

    when the button is touched the cell calls the delegate(ViewController), which updates the isExpandedArray accordingly and reloads the particular cell.

    CollectionViewCell

     protocol ExpandedCellDelegate:NSObjectProtocol{
        func topButtonTouched(indexPath:IndexPath)
    }
    
    class ExpandableCell: UICollectionViewCell {
    
        @IBOutlet weak var topButton: UIButton!
        weak var delegate:ExpandedCellDelegate?
    
        public var indexPath:IndexPath!
    
        @IBAction func topButtonTouched(_ sender: UIButton) {
            if let delegate = self.delegate{
                delegate.topButtonTouched(indexPath: indexPath)
            }
        }
    }
    

    View Controller Class

    class ViewController: UIViewController {
    
        @IBOutlet weak var collectionView: UICollectionView!
        var expandedCellIdentifier = "ExpandableCell"
    
        var cellWidth:CGFloat{
            return collectionView.frame.size.width
        }
         var expandedHeight : CGFloat = 200
         var notExpandedHeight : CGFloat = 50
    
         var dataSource = ["data0","data1","data2","data3","data4"]
         var isExpanded = [Bool]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            isExpanded = Array(repeating: false, count: dataSource.count)
        }
    }
    
    
    extension ViewController:UICollectionViewDataSource{
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return dataSource.count
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
              let cell = collectionView.dequeueReusableCell(withReuseIdentifier: expandedCellIdentifier, for: indexPath) as! ExpandableCell
                cell.indexPath = indexPath
                cell.delegate = self
                //configure Cell
                return cell
    
        }
    }
    
    extension ViewController:UICollectionViewDelegateFlowLayout{
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
            if isExpanded[indexPath.row] == true{
                 return CGSize(width: cellWidth, height: expandedHeight)
            }else{
                return CGSize(width: cellWidth, height: notExpandedHeight)
            }
    
        }
    
    }
    
    extension ViewController:ExpandedCellDelegate{
        func topButtonTouched(indexPath: IndexPath) {
            isExpanded[indexPath.row] = !isExpanded[indexPath.row]
            UIView.animate(withDuration: 0.8, delay: 0.0, usingSpringWithDamping: 0.9, initialSpringVelocity: 0.9, options: UIViewAnimationOptions.curveEaseInOut, animations: {
                  self.collectionView.reloadItems(at: [indexPath])
                }, completion: { success in
                    print("success")
            })
        }
    }
    
    0 讨论(0)
提交回复
热议问题