UICollectionViewCells
자동 레이아웃을 사용하여 자체 크기 조정을 시도하고 있지만 셀 크기를 내용에 맞게 조정할 수는 없습니다. 셀의 contentView 안에있는 내용에서 셀 크기가 어떻게 업데이트되는지 이해하는 데 어려움이 있습니다.
내가 시도한 설정은 다음과 같습니다.
- 사용자
UICollectionViewCell
A를UITextView
그있는 contentView한다. - 에 대한 스크롤
UITextView
이 비활성화되었습니다. - contentView의 가로 제약 조건은 “H : | [_textView (320)]”입니다. 즉,
UITextView
명시 적 너비가 320 인 셀의 왼쪽에 고정됩니다. - contentView의 수직 제약은 “V : | -0-[_ textView]”입니다. 즉
UITextView
, 셀 상단에 고정됩니다. - 는
UITextView
상수로 설정 높이 제약이UITextView
보고서는 텍스트에 맞게됩니다.
셀 배경이 빨간색으로 UITextView
설정되고 배경이 파란색으로 설정된 모습은 다음과 같습니다 .
답변
스위프트 5 업데이트
preferredLayoutAttributesFittingAttributes
이름 변경 preferredLayoutAttributesFitting
및 자동 크기 조정 사용
스위프트 4 업데이트
systemLayoutSizeFittingSize
로 개명 systemLayoutSizeFitting
iOS 9 용으로 업데이트
iOS 9에서 GitHub 솔루션이 중단 된 것을보고 마침내 문제를 완전히 조사 할 시간을 얻었습니다. 자체 크기 조정 셀에 대한 서로 다른 구성의 몇 가지 예를 포함하도록 저장소를 업데이트했습니다. 내 결론은 자기 사이징 셀은 이론적으로는 훌륭하지만 실제로는 지저분하다는 것입니다. 자체 크기 조정 셀을 진행할 때주의 할 사항.
TL; DR
내 GitHub 프로젝트를 확인하십시오
자체 크기 조정 셀은 플로우 레이아웃에서만 지원되므로 사용중인 것이 맞는지 확인하십시오.
자체 크기 조정 셀이 작동하려면 설정해야 할 두 가지가 있습니다.
1. 설정 estimatedItemSize
에UICollectionViewFlowLayout
estimatedItemSize
속성 을 설정하면 흐름 레이아웃이 실제로 동적이 됩니다.
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
2. 셀 서브 클래스 크기 조정 지원 추가
이것은 2 가지 맛으로 나옵니다. 의 자동 레이아웃 또는 맞춤 재정의 preferredLayoutAttributesFittingAttributes
.
자동 레이아웃으로 셀 생성 및 구성
셀의 제약 조건을 구성하는 것에 대한 훌륭한 SO 게시물 이 있기 때문에 이에 대해 자세히 설명하지 않습니다 . 것을 그냥 조심 엑스 코드 (6) 파산 당신이 아이폰 OS 7 지원하는 경우 아이폰 OS 7 그래서 함께 잔뜩, 당신은 autoresizingMask 셀의 경계 때와 같이 설정되어있는 contentView의 경계 셀의있는 contentView에와 있다는 설정되어 있는지 확인 같은 물건을 수행해야합니다 셀이로드됩니다 (예 🙂 awakeFromNib
.
알아야 할 사항은 셀이 테이블 뷰 셀보다 더 심각하게 제한되어야한다는 것입니다. 예를 들어 너비를 동적으로 만들려면 셀에 높이 제한이 필요합니다. 마찬가지로, 높이를 동적으로하려면 셀에 대한 너비 제한이 필요합니다.
preferredLayoutAttributesFittingAttributes
커스텀 셀에서 구현
이 기능이 호출되면 뷰가 이미 컨텐츠로 구성되었습니다 (예 : cellForItem
호출). 제약 조건이 적절하게 설정되었다고 가정하면 다음과 같이 구현할 수 있습니다.
//forces the system to do one layout pass
var isHeightCalculated: Bool = false
override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
//Exhibit A - We need to cache our calculation to prevent a crash.
if !isHeightCalculated {
setNeedsLayout()
layoutIfNeeded()
let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
var newFrame = layoutAttributes.frame
newFrame.size.width = CGFloat(ceilf(Float(size.width)))
layoutAttributes.frame = newFrame
isHeightCalculated = true
}
return layoutAttributes
}
참고 iOS 9에서는주의하지 않으면 구현에서 충돌이 발생할 수있는 동작이 약간 변경되었습니다 (자세한 내용은 여기 참조 ). 구현할 때 preferredLayoutAttributesFittingAttributes
레이아웃 속성의 프레임 만 한 번만 변경해야합니다. 이 작업을 수행하지 않으면 레이아웃이 구현을 무기한 호출하고 결국 충돌합니다. 한 가지 해결책은 셀에서 계산 된 크기를 캐시하고 셀을 재사용하거나 isHeightCalculated
속성으로 수행 한 내용을 변경할 때마다 무효화하는 것입니다 .
레이아웃 경험
이 시점에서 collectionView에 ‘작동하는’동적 셀이 있어야합니다. 아직 테스트 중에 충분한 기본 솔루션을 찾지 못 했으므로 언제든지 의견을 말하십시오. 여전히 UITableView
역동적 인 사이징 IMHO와의 싸움에서이기는 것 같습니다 .
경고
프로토 타입 셀을 사용하여 추정 된 항목 크기 를 계산하는 경우 XIB가 크기 클래스를 사용 하면 중단됩니다 . 그 이유는 XIB에서 셀을로드 할 때 크기 클래스가로 구성되기 때문입니다 Undefined
. iOS 7에서는 크기 클래스가 장치 (iPad = Regular-Any, iPhone = Compact-Any)를 기반으로로드되기 때문에 iOS 8 이상에서만 손상됩니다. XIB를로드하지 않고 추정 된 항목 크기를 설정하거나 XIB에서 셀을로드하고 collectionView에 추가하고 (traitCollection을 설정 함) 레이아웃을 수행 한 다음 슈퍼 뷰에서 제거 할 수 있습니다. 또는 셀이 traitCollection
게터를 재정의 하고 적절한 특성을 반환 하도록 할 수도 있습니다 . 그것은 당신에게 달려 있습니다.
내가 놓친 것이 있으면 알려주세요. 도움이 되길 바랍니다. 행운을 빌어 요.
답변
iOS10에는 UICollectionViewFlowLayout.automaticSize
(이전 UICollectionViewFlowLayoutAutomaticSize
) 이라는 새로운 상수가 있으므로 대신 :
self.flowLayout.estimatedItemSize = CGSize(width: 100, height: 100)
이것을 사용할 수 있습니다 :
self.flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
컬렉션 뷰의 셀에 일정한 wid가있는 경우 특히 성능이 향상됩니다.
흐름 레이아웃 액세스 :
override func viewDidLoad() {
super.viewDidLoad()
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
}
}
스위프트 5 업데이트 :
override func viewDidLoad() {
super.viewDidLoad()
if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
}
}
답변
Daniel Galasko의 답변에 대한 몇 가지 주요 변경 사항 모든 문제가 해결되었습니다. 불행히도, 나는 직접적으로 (아직도) 언급할만한 명성을 얻지 못했습니다.
1 단계에서 자동 레이아웃을 사용할 때 셀에 단일 상위 UIView를 추가하기 만하면됩니다. 셀 내부의 모든 것은 부모의 하위 뷰 여야합니다. 그것은 내 모든 문제에 답했다. Xcode는 UITableViewCells에 이것을 자동으로 추가하지만 UICollectionViewCells에는 그렇지 않습니다. 문서 에 따르면 :
셀 모양을 구성하려면 dataView 속성의보기에 데이터 항목의 내용을 하위보기로 표시하는 데 필요한보기를 추가하십시오. 셀 자체에 하위 뷰를 직접 추가하지 마십시오.
그런 다음 3 단계를 완전히 건너 뜁니다. 필요하지 않습니다.
답변
iOS 10 이상에서는 매우 간단한 2 단계 프로세스입니다.
-
모든 셀 내용이 단일 UIView (또는 UIStackView와 같은 UIView의 하위 항목) 내에 배치되어 자동 레이아웃을 많이 단순화해야합니다. UITableViewCells의 크기를 동적으로 조정하는 것처럼 전체 뷰 계층에는 가장 바깥 쪽 컨테이너에서 가장 안쪽 뷰까지 제약 조건이 구성되어 있어야합니다. UICollectionViewCell과 즉각적인 childview 사이의 제약 조건이 포함됩니다.
-
UICollectionView의 flowlayout에 자동 크기 조정을 지시하십시오.
yourFlowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
답변
-
viewDidLoad ()에 flowLayout 추가
override func viewDidLoad() { super.viewDidLoad() if let flowLayout = infoCollection.collectionViewLayout as? UICollectionViewFlowLayout { flowLayout.estimatedItemSize = CGSize(width: 1, height:1) } }
-
또한 UIView를 셀의 mainContainer로 설정하고 셀에 필요한 모든보기를 추가하십시오.
-
자세한 내용은이 멋진 튜토리얼을 참조하십시오
.iOS 9 및 10에서 자동 레이아웃을 사용하여 자동 크기 조정 셀이있는 UICollectionView
답변
11/19/19 편집 : iOS 13의 경우 UICollectionViewCompositionalLayout을 예상 높이와 함께 사용하십시오. 이 깨진 API를 다루는 데 시간을 낭비하지 마십시오.
일정 시간 동안이 문제를 해결 한 후 스크롤을 비활성화하지 않으면 UITextViews에서 크기 조정이 작동하지 않는 것으로 나타났습니다.
let textView = UITextView()
textView.scrollEnabled = false
답변
contentView 앵커 미스터리 :
하나의 기괴한 경우
contentView.translatesAutoresizingMaskIntoConstraints = false
작동하지 않습니다. contentView에 네 개의 명시 적 앵커를 추가하고 작동했습니다.
class AnnoyingCell: UICollectionViewCell {
@IBOutlet var word: UILabel!
override init(frame: CGRect) {
super.init(frame: frame); common() }
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder); common() }
private func common() {
contentView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
contentView.leftAnchor.constraint(equalTo: leftAnchor),
contentView.rightAnchor.constraint(equalTo: rightAnchor),
contentView.topAnchor.constraint(equalTo: topAnchor),
contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
])
}
}
평소와 같이
estimatedItemSize = UICollectionViewFlowLayout.automaticSize
에 YourLayout: UICollectionViewFlowLayout
누가 알아? 누군가를 도울 수 있습니다.
신용
https://www.vadimbulavin.com/collection-view-cells-self-sizing/
그 팁을 우연히 발견했습니다-이것에 관한 1000 년대 기사의 다른 곳에서는 그것을 보지 못했습니다.
