UICollectionViewFlowLayout最大间距设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
// DanceTeamSearchLayout.swift
// boosjdance
//
// Created by boosj on 16/8/29.
// Copyright © 2016年 cz. All rights reserved.
//
//swift3
import UIKit
/// 舞队 搜索记录的layout
class DanceTeamSearchLayout: UICollectionViewFlowLayout {
//我们想设置的最大间距,可根据需要改
//var maximumSpacing:CGFloat = 10
/**
重写当前方法 实现控制item最大间距
- parameter rect: rect 绘图范围
- returns: item属性数组
*/
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect)
if attributes != nil{
for i in 0 ..< attributes!.count{
if i == 0{
let current = attributes![i]
var frame = current.frame
frame.origin.x = 10
current.frame = frame
continue
}
//当前attributes
let current = attributes![i]
//上一个attributes
let prevLayoutAttributes = attributes![ (i - 1)]
//前一个cell的最右边
let origin = prevLayoutAttributes.frame.maxX
// var yOffset = current.frame.origin.y
//如果当前一个cell的最右边加上我们想要的间距加上当前cell的宽度依然在contentSize中,我们改变当前cell的原点位置
//不加这个判断的后果是,UICollectionView只显示一行,原因是下面所有cell的x值都被加到第一行最后一个元素的后面了
// self.minimumInteritemSpacing 列间距
if (origin + self.minimumInteritemSpacing + current.frame.size.width)<self.collectionViewContentSize.width{
var frame = current.frame
frame.origin.x = origin + self.minimumInteritemSpacing
current.frame = frame
}else{
var frame = current.frame
frame.origin.x = self.sectionInset.left // 边缘的预留宽度
// frame.origin.y = yOffset + frame.height + maximumSpacing
current.frame = frame
}
// printLog("cell测试frame: \(current.frame)")
}
}
return attributes
}
/*
如果我们的布局是会时刻变化的, 需要在滚动的过程中重新布局 , 那么我们需要
设置这个方法的返回值为true, 默认为false
* 当返回值为true的时候会将collectionView的layout设置为invalidated,
将会使collectionView重新调用上面的prepareLayout()...方法重新获得布局
* 同时, 当屏幕旋转的时候collectionView的bounds也会调用这个方法
如果设置为false, 那么将不会达到屏幕适配的效果,
* 需要注意的是, 当collectionView执行一些操作(delete insert reload)等的时候,
不会调用这个方法, 会直接重新调用上面的prepareLayout()...方法重新获得布局
*/
// override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
// return true
// }
}

一个左对齐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//
// UICollectionViewLeftAlignedLayout.swift
// test
//
// Created by boosj on 2017/8/14.
// Copyright © 2017年 boosjcz. All rights reserved.
//
import UIKit
extension UICollectionViewLayoutAttributes {
/** 每行第一个item左对齐 **/
func leftAlignFrame(_ sectionInset:UIEdgeInsets) {
var frame = self.frame
frame.origin.x = sectionInset.left
self.frame = frame
}
}
class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {
//MARK: - 重新UICollectionViewFlowLayout的方法
override init() {
super.init()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/** Collection所有的UICollectionViewLayoutAttributes */
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributesToReturn = super.layoutAttributesForElements(in: rect)!
var attributesCopy = [UICollectionViewLayoutAttributes]()
for attributes in attributesToReturn {
if nil == attributes.representedElementKind {
let itemAttributesCopy = attributes.copy() as! UICollectionViewLayoutAttributes
let indexPath = itemAttributesCopy.indexPath
itemAttributesCopy.frame = self.layoutAttributesForItem(at: indexPath)!.frame
// manipulate itemAttributesCopy
attributesCopy.append(itemAttributesCopy)
}else{
// 忘记把这里app下 所以才没有进 头部代理
attributesCopy.append(attributes)
}
}
return attributesCopy // (copy 版 数据 防止警告 ,但是会无发进入头部代理)
}
//
/** 每个item的UICollectionViewLayoutAttributes */
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
//现在item的UICollectionViewLayoutAttributes
let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as! UICollectionViewLayoutAttributes
//现在section的sectionInset
let sectionInset = self.evaluatedSectionInset(indexPath.section)
//是否是section的第一个item
let isFirstItemInSection = indexPath.item == 0
//出去section偏移量的宽度
let layoutWidth: CGFloat = self.collectionView!.frame.width - sectionInset.left - sectionInset.right
//是section的第一个item
if isFirstItemInSection {
//每行第一个item左对齐
currentItemAttributes.leftAlignFrame(sectionInset)
return currentItemAttributes
}
//前一个item的NSIndexPath
let previousIndexPath = IndexPath(item: indexPath.item - 1, section: indexPath.section)
//前一个item的frame
let previousFrame = self.layoutAttributesForItem(at: previousIndexPath)!.frame
//为现在item计算新的left
let previousFrameRightPoint: CGFloat = previousFrame.origin.x + previousFrame.size.width
//现在item的frame
let currentFrame = currentItemAttributes.frame
//现在item所在一行的frame
let strecthedCurrentFrame = CGRect(x: sectionInset.left, y: currentFrame.origin.y, width: layoutWidth, height: currentFrame.size.height)
//previousFrame和strecthedCurrentFrame是否有交集,没有,说明这个item和前一个item在同一行,item是这行的第一个item
let isFirstItemInRow = !previousFrame.intersects(strecthedCurrentFrame)
//item是这行的第一个item
if isFirstItemInRow {
//每行第一个item左对齐
currentItemAttributes.leftAlignFrame(sectionInset)
return currentItemAttributes
}
//不是每行的第一个item
var frame = currentItemAttributes.frame
//为item计算新的left = previousFrameRightPoint + item之间的间距
frame.origin.x = previousFrameRightPoint + self.evaluatedMinimumInteritemSpacing(indexPath.item)
//为item的frame赋新值
currentItemAttributes.frame = frame
return currentItemAttributes
}
//MARK: - System
/** item行间距 **/
fileprivate func evaluatedMinimumInteritemSpacing(_ ItemAtIndex:Int) -> CGFloat {
if let delete = self.collectionView?.delegate {
weak var delegate = (delete as! UICollectionViewDelegateFlowLayout)
if delegate!.responds(to: #selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:minimumInteritemSpacingForSectionAt:))) {
let mini = delegate?.collectionView!(self.collectionView!, layout: self, minimumInteritemSpacingForSectionAt: ItemAtIndex)
if mini != nil {
return mini!
}
}
}
return self.minimumInteritemSpacing
}
/** section的偏移量 **/
fileprivate func evaluatedSectionInset(_ itemAtIndex:Int) -> UIEdgeInsets {
if let delete = self.collectionView?.delegate {
weak var delegate = (delete as! UICollectionViewDelegateFlowLayout)
if delegate!.responds(to: #selector(UICollectionViewDelegateFlowLayout.collectionView(_:layout:insetForSectionAt:))) {
let sectionInset = delegate?.collectionView!(self.collectionView!, layout: self, insetForSectionAt: itemAtIndex)
if sectionInset != nil {
return sectionInset!
}
}
}
return self.sectionInset
}
}
Author

陈昭

Posted on

2016-08-29

Updated on

2021-12-27

Licensed under

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

Kommentare

You forgot to set the shortname for Disqus. Please set it in _config.yml.