ios - systemlayoutsizefitting - uicollectionview estimated size




Storyboard에서 AutoLayout을 사용하는 UICollectionViewCell의 가변 폭 및 높이(XIB 제외) (2)

다음은 AutoLayout, UICollectionView 및 UICollectionViewCell을 사용하는 응용 프로그램의 디자인 문제입니다.이 문제는 AutoLayout 제약 조건 및 내용 (일부 텍스트)에 따라 너비 및 높이를 자동으로 조정할 수 있습니다.

그것은 각 셀의 내용에 따라 각 행에 대해 별도로 계산 된 자체 너비 및 높이를 가진 각 셀과 마찬가지로 UITableView 목록입니다. 그것은 iOS 메시지가 app (또는 WhatsUp)에 빌드 된 것과 같습니다.

응용 프로그램이 func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize 사용해야한다는 것은 명백합니다.

문제는 해당 메서드 내에서 응용 프로그램 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 또는 dequeueReusableCellWithReuseIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath!) -> AnyObjectdequeueReusableCellWithReuseIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath!) -> AnyObject 하여 셀을 인스턴스화하고 특정 내용으로 채 웁니다. 너비와 높이를 계산합니다. 그렇게하려고하면 (적어도 iOS 8.3에서는) 무한 반복 호출이나 다른 유형의 앱 충돌이 발생합니다.

이 상황을 해결하는 가장 가까운 방법은 셀의 정의를 뷰 계층으로 복사하여 자동 레이아웃이 셀을 자동으로 (셀이 부모 콜렉션 뷰와 동일한 너비를 갖도록) 크기를 조정할 수 있도록하므로 앱이 특정 내용으로 셀을 구성 할 수 있으며 크기를 계산하십시오. 중복 된 자원으로 인해이 문제를 해결할 수있는 유일한 방법은 아닙니다.

그 모두는 UILabel.preferredMaxLayoutWidth를 자동 너비 및 높이 또는 적어도 자동 레이아웃 제약 조건 정의에 따라 달라질 수있는 자동 레이아웃 제어 가능 (하드 코드되지 않음)이어야하는 값으로 설정하므로 앱에서 여러 줄의 UILabel 내장 함수를 가져올 수 있습니다 크기 계산.

Storyboards는 오늘날의 산업 표준이어야하며 코드에 개입하지 않는 편이 좋기 때문에 XIB 파일에서 셀을 인스턴스화하고 싶지 않습니다.

편집하다:

실행할 수없는 기본 코드는 다음과 같습니다. 따라서 변수 cellProbe (사용되지 않음) 만 인스턴스화하면 앱이 다운됩니다. 전화가 없으면 앱이 원활하게 실행됩니다.

var onceToken: dispatch_once_t = 0

class ViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

        dispatch_once(&onceToken) {

            let cellProbe = collectionView.dequeueReusableCellWithReuseIdentifier("first", forIndexPath: NSIndexPath(forRow: 0, inSection: 0)) as! UICollectionViewCell
        }

        return CGSize(width: 200,height: 50)
    }

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("first", forIndexPath: NSIndexPath(forRow: 0, inSection: 0)) as! UICollectionViewCell

        return cell
    }
}

자동 레이아웃을 사용하여 표보기 셀 높이를 동적으로 크기를 조정할 때 전화가 필요하지 않은 것처럼

func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell

...에서

optional func tableView(_ tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat

적절한 방법은 사용자 지정 셀의 클래스 메서드와 같은 높이 계산을위한 로컬 정적 셀을 만드는 것입니다.

+ (CGFloat)cellHeightForContent:(id)content tableView:(UITableView *)tableView {
    static CustomCell *cell;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        cell = [tableView dequeueReusableCellWithIdentifier:[CustomCell cellIdentifier]];
    });

    Item *item = (Item *)content;
    configureBasicCell(cell, item);

    [cell setNeedsLayout];
    [cell layoutIfNeeded];
    CGSize size = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    return size.height + 1.0f; // Add 1.0f for the cell separator height
}

나는 스토리 보드가 산업 표준이라는 것을 심각하게 의심합니다. xib는 tableViewCell 및 CollectionViewCell을 포함한 뷰와 같은 사용자 정의 셀을 생성하는 가장 좋은 방법입니다.


제약 조건을 사용하는 경우 셀당 크기를 설정할 필요가 없습니다. 그래서 당신은 대리자 메서드 func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize

대신 정확한 크기를 아직 알지 못한다고 레이아웃에 알려주는 CGSizeZero 이외의 값으로 이것을 설정하여 estimatedItemSize 의 크기를 설정해야합니다. 레이아웃은 각 셀에 크기를 묻고 필요시 계산해야합니다.

let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.estimatedItemSize = someReasonableEstimatedSize()




height