Auto-sizing UICollectionView headers

偶尔善良 提交于 2020-01-12 19:31:35

问题


I'm trying to make a detail screen for a to-do list kind of app. Here's what the detail screen currently looks like:

This is a UICollectionViewController, with a header. The header contains 2 UILabel objects, and a UITextView object. The layout of these objects is managed by a vertical UIStackView. A UIView is used to set a white background.

I'm having some difficulties in defining the height of this UICollectionReusableView at runtime. Any advice is appreciated.


回答1:


This is a bit of a hack, but seems to work.

    // showhere to keep a reference
    UICollectionReusableView * _cachedHeaderView;


    - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView 
               viewForSupplementaryElementOfKind:(NSString *)kind 
                                     atIndexPath:(NSIndexPath *)indexPath{

        if(!_cachedHeaderView){
            // dequeue the cell from storyboard
            _cachedHeaderView = 
         [collectionView dequeueReusableCellWithReuseIdentifier:@"header_cell" 
                                                   forIndexPath:indexPath];

            // set captions/images on the header etc...

            // tell the collectionview to redraw this section
          [self.collectionView reloadSections:[NSIndexSet 
                            indexSetWithIndex:indexPath.section]];
        }

        return _cachedHeaderView;
    }


        - (CGSize)collectionView:(UICollectionView *)collectionView 
                          layout:(UICollectionViewLayout*)collectionViewLayout        
 referenceSizeForHeaderInSection:(NSInteger)section{

        // once there is a reference ot the view, use it to figure out the height
        if(_cachedHeaderView){
            CGSize size = 
[_cachedHeaderView systemLayoutSizeFittingSize:collectionView.bounds.size 
                 withHorizontalFittingPriority:UILayoutPriorityRequired 
                       verticalFittingPriority:UILayoutPriorityDefaultLow];
            return size;

        }

        // a placeholder value just to get the dequeueReusableCellWithReuseIdentifier to work 
        return CGSizeMake(collectionView.bounds.size.width, 100);
    }




回答2:


Here is how you can handle custom UICollectionViewReusableView with auto layout without the XIB file.

  1. Implement the referenceSizeForHeaderInSection delegate method.
  2. In it, instantiate the view that you use as a header view.
  3. Set its visibility to hidden, to avoid flashing.
  4. Add the view to the collectionview's superview.
  5. Set it's layout using auto layout, to match the expected visual outcome of the header.
  6. Invoke setNeedsLayout and layoutIfNeeded
  7. Remove the view from the superview

CAUTION: I am not a big fan of this solution, as it adds the custom view to the collectionview's superview each time, to perform calculations. I didn't notice any performance issues though.

CAUTION #2: I'd treat it as a temporary solution, and migrate to self sizing supplementary views once they get published.

I am using PureLayout for autolayout purposes.

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {

    let header = CustomHeaderView()

        header.isHidden = true;
        self.view.addSubview(header)
        header.autoPinEdge(toSuperviewEdge: .leading)
        header.autoPinEdge(toSuperviewEdge: .trailing)
        header.autoPin(toTopLayoutGuideOf: self, withInset: 0)
        header.setupHeader(withData: self.data)
        header.setNeedsLayout()
        header.layoutIfNeeded()
        header.removeFromSuperview()

        return header.frame.size
}


来源:https://stackoverflow.com/questions/39201748/auto-sizing-uicollectionview-headers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!