Dynamic UICollectionView header size based on UILabel

前端 未结 8 1992
梦谈多话
梦谈多话 2020-12-08 04:51

I\'ve read a bunch of posts on adding header to UICollectionView. In an iOS 7+ app in Swift, I\'m trying to add a header with a UILabel in it whose height should adjust base

8条回答
  •  忘掉有多难
    2020-12-08 05:34

    The idea is to have a template header instance in memory to calculate the desired height before creating the result header view. You should move your section header view to a separate .nib file, setup all autolayout constraints and instantiate the template in your viewDidLoad method like this:

    class MyViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
      @IBOutlet var collectionView : UICollectionView?
      private var _templateHeader : MyHeaderView
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
        let nib = UINib(nibName: "HeaderView", bundle:nil)
        self.collectionView?.registerNib(nib, forCellWithReuseIdentifier: "header_view_id")
    
        _templateHeader = nib.instantiateWithOwner(nil, options:nil)[0] as! MyHeaderView
      }
    
    }
    

    Then you will be able to calculate the header size (height in my example) in your flow layout delegate method:

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    
        _templateHeader.lblTitle.text = "some title here"
        _templateHeader.lblDescription.text = "some long description"
    
        _templateHeader.setNeedsUpdateConstraints();
        _templateHeader.updateConstraintsIfNeeded()
    
        _templateHeader.setNeedsLayout();
        _templateHeader.layoutIfNeeded();
    
        let computedSize = _templateHeader.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
    
        return CGSizeMake(collectionView.bounds.size.width, computedSize.height);
    }
    

    And then create and return your regular header view as always, since you have already calculated its size in flow layout delegate method:

    func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath: NSIndexPath) -> UICollectionReusableView {
    
        switch kind {
    
        case UICollectionElementKindSectionHeader:
    
            let headerView = collectionView.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: "header_view_id", forIndexPath: indexPath) as! MyHeaderView
            headerView.lblTitle.text = "some title here"
            headerView.lblDescription.text = "some long description"
    
            headerView.setNeedsUpdateConstraints()
            headerView.updateConstraintsIfNeeded()
    
            headerView.setNeedsLayout()
            headerView.layoutIfNeeded()
    
            return headerView
        default:
            assert(false, "Unexpected kind")
        }
    
    }
    

    Forgot to say about one important moment - your header view should have an autolayout constraint on its contentView to fit the collection view width (plus or minus the desired margins).

提交回复
热议问题