iOS 사용자 정의 UICollection View Layout 폭포 흐름 레이아웃 구현
6116 단어 iOSUICollectionViewLayout폭포 류
최근 프로젝트 에 서 는 폭포 류 의 효 과 를 사용 해 야 하 는데,UICollection View Flow Layout 로 는 효 과 를 보지 못 하고 폭포 류 의 layot 를 직접 썼 습 니 다.다음은 제 마음의 거리 입 니 다.
선행 효과 도와demo 주소:
UICollectionView 로 폭포 흐름 을 실현 하기 때문에 UICollectionView Layout 를 계승 하여 하나의 layot 를 정의 하여 간단 한 폭포 흐름 의 구 조 를 실현 하기 로 결 정 했 습 니 다.다음은 다시 쓰 는 방법 입 니 다.
이 속성 을 다시 쓰 면 UICollection View 의 ContentSize:collection View ContentSize 를 얻 을 수 있 습 니 다.
이 방법 을 다시 써 서 각 아 이 템 의 레이아웃 을 가 져 옵 니 다:layout Attributes ForItem(at indexPath:IndexPath)->UICollection View LayoutAttributes?
이 방법 을 다시 쓰 면 UICollection View 의 모든 아 이 템 의 레이아웃 을 보 여 줍 니 다:layoutAttributes ForElements(in rect:CGRect)->[UICollection View LayoutAttributes]?
이 방법 을 다시 써 서 UICollectionView 전 동작:prepare()
사고의 방향 을 실현 하 다.
프 록 시 모드 를 통 해 필요 한 열 수 와 각 아 이 템 의 높이 를 얻 을 수 있 습 니 다.과 열 수 와 열 사이 의 간격 과 UICollection View 의 너비 로 각 열의 폭 을 얻 을 수 있 습 니 다.item 은 왼쪽 에서 오른쪽으로 배치 하고 다음 열의 item 은 높이 가 가장 작은 열 아래 에 놓 아 각 열의 높이 가 고 르 지 않 은 것 을 방지 합 니 다.아래 에 코드 와 설명 을 붙 입 니 다.
import UIKit
@objc protocol WCLWaterFallLayoutDelegate {
//waterFall
func columnOfWaterFall(_ collectionView: UICollectionView) -> Int
// item
func waterFall(_ collectionView: UICollectionView, layout waterFallLayout: WCLWaterFallLayout, heightForItemAt indexPath: IndexPath) -> CGFloat
}
class WCLWaterFallLayout: UICollectionViewLayout {
//
weak var delegate: WCLWaterFallLayoutDelegate?
//
@IBInspectable var lineSpacing: CGFloat = 0
//
@IBInspectable var columnSpacing: CGFloat = 0
//section top
@IBInspectable var sectionTop: CGFloat = 0 {
willSet {
sectionInsets.top = newValue
}
}
//section Bottom
@IBInspectable var sectionBottom: CGFloat = 0 {
willSet {
sectionInsets.bottom = newValue
}
}
//section left
@IBInspectable var sectionLeft: CGFloat = 0 {
willSet {
sectionInsets.left = newValue
}
}
//section right
@IBInspectable var sectionRight: CGFloat = 0 {
willSet {
sectionInsets.right = newValue
}
}
//section Insets
@IBInspectable var sectionInsets: UIEdgeInsets = UIEdgeInsets.zero
//
private var columnHeights: [Int: CGFloat] = [Int: CGFloat]()
private var attributes: [UICollectionViewLayoutAttributes] = [UICollectionViewLayoutAttributes]()
//MARK: Initial Methods
init(lineSpacing: CGFloat, columnSpacing: CGFloat, sectionInsets: UIEdgeInsets) {
super.init()
self.lineSpacing = lineSpacing
self.columnSpacing = columnSpacing
self.sectionInsets = sectionInsets
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
//MARK: Public Methods
//MARK: Override
override var collectionViewContentSize: CGSize {
var maxHeight: CGFloat = 0
for height in columnHeights.values {
if height > maxHeight {
maxHeight = height
}
}
return CGSize.init(width: collectionView?.frame.width ?? 0, height: maxHeight + sectionInsets.bottom)
}
override func prepare() {
super.prepare()
guard collectionView != nil else {
return
}
if let columnCount = delegate?.columnOfWaterFall(collectionView!) {
for i in 0..<columnCount {
columnHeights[i] = sectionInsets.top
}
}
let itemCount = collectionView!.numberOfItems(inSection: 0)
attributes.removeAll()
for i in 0..<itemCount {
if let att = layoutAttributesForItem(at: IndexPath.init(row: i, section: 0)) {
attributes.append(att)
}
}
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
if let collectionView = collectionView {
// indexPath item attributes
let att = UICollectionViewLayoutAttributes.init(forCellWith: indexPath)
// collectionView
let width = collectionView.frame.width
if let columnCount = delegate?.columnOfWaterFall(collectionView) {
guard columnCount > 0 else {
return nil
}
//item = (collectionView - ) /
let totalWidth = (width - sectionInsets.left - sectionInsets.right - (CGFloat(columnCount) - 1) * columnSpacing)
let itemWidth = totalWidth / CGFloat(columnCount)
// item ,
let itemHeight = delegate?.waterFall(collectionView, layout: self, heightForItemAt: indexPath) ?? 0
//
var minIndex = 0
for column in columnHeights {
if column.value < columnHeights[minIndex] ?? 0 {
minIndex = column.key
}
}
// item x
let itemX = sectionInsets.left + (columnSpacing + itemWidth) * CGFloat(minIndex)
//item y = y +
let itemY = (columnHeights[minIndex] ?? 0) + lineSpacing
// attributes frame
att.frame = CGRect.init(x: itemX, y: itemY, width: itemWidth, height: itemHeight)
// y
columnHeights[minIndex] = att.frame.maxY
}
return att
}
return nil
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attributes
}
}
마지막 으로demo 주소..마음 에 드 시 면 스타 해 주세요.위 는 간단 한 폭포 흐름 의 실현 과정 입 니 다.여러분 들 이 배 울 수 있 는 것 이 많 고 고려 할 부분 이 부족 합 니 다.여러분 들 이 교류 하고 공부 하 는 것 을 환영 합 니 다.읽 어 주 셔 서 감사합니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
View의 레이아웃 방법을 AutoLayout에서 따뜻한 손 계산으로 하면 성능이 9.26배로 된 이야기이 기사는 의 15 일째 기사입니다. 어제는 에서 이었습니다. 손 계산을 권하는 의도는 없고, 특수한 상황하에서 계측한 내용입니다 화면 높이의 10 배 정도의 contentView가있는 UIScrollView 레이아...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.