成品图

首先可以看出是使用UICollectionView
为基础构建的,我们先声明一个View继承自UICollectionView
,并且遵循UICollectionViewDelegate
和UICollectionViewDataSource
1 2 3
| class SelectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource { }
|
然后声明一些基础的需要用到的常变量
1 2 3 4 5 6
| private let cellId = "SELECTION_VIEW_CELL_ID" private var selectedIdx: Int = -1 private var data: [String] private var callBack: ((Int)->Void)?
var allowsCancelSelection: Bool = false
|
然后填写一下初始化函数和回调,可以讲的一点主要是didSelect函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { if callBack != nil { callBack!(indexPath.row) }
if selectedIdx == -1 { selectedIdx = indexPath.row (collectionView.cellForItem(at: indexPath) as! FBTagCollectionViewCell).toggle() } else if selectedIdx == indexPath.row { if allowsCancelSelection { selectedIdx = -1 (collectionView.cellForItem(at: indexPath) as! FBTagCollectionViewCell).toggle() } return } else { (collectionView.cellForItem(at: IndexPath(row: selectedIdx, section: indexPath.section)) as! FBTagCollectionViewCell).toggle() (collectionView.cellForItem(at: indexPath) as! FBTagCollectionViewCell).toggle() selectedIdx = indexPath.row } }
|
可以看到对于一些条件进行了判断,以及让回调函数能够获取到选择的下标,cell的toggle()函数用于改变背景颜色(即选中状态)
再添加一些供外部调用的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| extension SelectionView { func getIdx() -> Int { return selectedIdx } func addCallBack(_ callBack: @escaping ((Int)->Void)) { self.callBack = callBack } func updateData(data: [String]) { self.data = data reloadData() } }
|
大功告成,以下是完整代码。
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
| import UIKit
class SelectionView: UICollectionView, UICollectionViewDelegate, UICollectionViewDataSource { private let cellId = "SELECTION_VIEW_CELL_ID" private var selectedIdx: Int = -1 private var data: [String] private var callBack: ((Int)->Void)? var allowsCancelSelection: Bool = false init(data: [String], collectionViewLayout: UICollectionViewFlowLayout, callBack: ((Int)->Void)? = nil) { self.data = data self.callBack = callBack super.init(frame: .zero, collectionViewLayout: collectionViewLayout) register(FBTagCollectionViewCell.self, forCellWithReuseIdentifier: cellId) backgroundColor = .white delegate = self dataSource = self } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return data.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FBTagCollectionViewCell cell.update(by: data[indexPath.row], selected: indexPath.row == selectedIdx) return cell } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { if callBack != nil { callBack!(selectedIdx == indexPath.row ? -1 : indexPath.row) } if selectedIdx == -1 { selectedIdx = indexPath.row (collectionView.cellForItem(at: indexPath) as! FBTagCollectionViewCell).toggle() } else if selectedIdx == indexPath.row { if allowsCancelSelection { selectedIdx = -1 (collectionView.cellForItem(at: indexPath) as! FBTagCollectionViewCell).toggle() } return } else { if let cell = collectionView.cellForItem(at: IndexPath(item: selectedIdx, section: indexPath.section)) { (cell as! FBTagCollectionViewCell).toggle() } (collectionView.cellForItem(at: indexPath) as! FBTagCollectionViewCell).toggle() selectedIdx = indexPath.row } } }
extension SelectionView { func getIdx() -> Int { return selectedIdx } func addCallBack(_ callBack: @escaping ((Int)->Void)) { self.callBack = callBack } func updateData(data: [String]) { self.data = data reloadData() } }
|