一個(gè)通用的標(biāo)簽瀑布流多選器(自定義選項(xiàng)樣式仗谆、統(tǒng)一的點(diǎn)擊切換處理)指巡。
小組件多選器依賴(lài)于 iOS 小組件 - 標(biāo)簽瀑布流Base組件抽取,APP業(yè)務(wù)重構(gòu)(一) 一文中的base組件胸私。
一厌处、需求
如設(shè)計(jì)圖所示,需要一個(gè)瀑布流的標(biāo)簽多選組件岁疼。
之前已經(jīng)寫(xiě)過(guò)一個(gè)瀑布流單選器(iOS 小組件 - 瀑布流單選器,技術(shù)設(shè)計(jì)與實(shí)現(xiàn)詳解(二))缆娃,以同樣的思路寫(xiě)一個(gè)新的多選器捷绒。
二、技術(shù)設(shè)計(jì)思路
第一贯要,需要一個(gè)能生成通用瀑布流多選器布局的組件暖侨。
第二,可以支持靈活自定義比較重要的字段 (選中文本顏色崇渗、選中文本背景顏色字逗、未選中文本顏色京郑、未選中背景顏色、字體葫掉、間距 等等)
第三些举,自動(dòng)處理選中與反選事件的樣式,返回點(diǎn)擊選中的回調(diào)俭厚。
總結(jié)户魏,因?yàn)榍拔囊呀?jīng)擁有了(第一)和(第二點(diǎn))大部份功能了,后面只需要做一些小細(xì)節(jié)上的處理就可以了挪挤。!!
三叼丑、多選器小組件源碼
BaseView
在這段代碼中,除去前文已經(jīng)完成的基礎(chǔ)功能外扛门,添加的小細(xì)節(jié)有:
-
var hasSelecedClosure: ((Bool) -> ())?
點(diǎn)擊標(biāo)簽回調(diào)鸠信,判斷是否已選夠目標(biāo)個(gè)數(shù)(可下一步)。
// 瀑布標(biāo)簽多選器
import UIKit
class YAYTagMultipleChoiceView: YAYBaseTagView {
/// 是否已選夠目標(biāo)個(gè)數(shù)(可下一步)
var hasSelecedClosure: ((Bool) -> ())?
/// 限制最少選中個(gè)數(shù)
var leastChoiceCount: Int = 1
override init(frame: CGRect, option: YAYBaseTagOption) {
super.init(frame: frame, option: option)
layout.scrollDirection = .vertical
backgroundColor = .clear
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/// 獲取已選擇標(biāo)簽
func getSelectedTags() -> ([YAYBaseTagModel]) {
var selectedTags = [YAYBaseTagModel]()
for tag in dataArray {
// 如果記錄了true论寨,即是選中狀態(tài)
if tag.isSelected ?? false {
selectedTags.append(tag)
}
}
return selectedTags
}
override func getSizeForItem(_ tagModel: YAYBaseTagModel, collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let tagModel = dataArray[indexPath.row]
let text = "\(tagModel.labelName)"
// 加5是因?yàn)樗愠鰜?lái)的寬度不夠字體顯示症副,有誤差
let width: CGFloat = text.textWidth(fontSize: option.fontSize, height: option.titleHeight, fontWeight: option.fontWeight) + option.itemLeftMargin + option.itemRightMargin + 5
// 超過(guò)限制,文本寬度要恢復(fù)才能出現(xiàn)...
return CGSize(width: min(option.contentWidth - 5, width), height: option.itemHeight)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: option.cellClass, for: indexPath) as? YAYTagMultipleChoiceCell ?? YAYTagMultipleChoiceCell()
cell.isSelected = dataArray[indexPath.row].isSelected ?? false
cell.tagOptionSet(option: option)
cell.bindData(model: dataArray[indexPath.row])
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
super.collectionView(collectionView, didSelectItemAt: indexPath)
// 數(shù)據(jù)源記錄政基,選中與反選
dataArray[indexPath.row].isSelected = !(dataArray[indexPath.row].isSelected ?? false)
self.reloadData()
// 是否已選夠目標(biāo)個(gè)數(shù)
if hasSelecedClosure != nil {
hasSelecedClosure?(getSelectedTags().count >= leastChoiceCount)
}
}
}
BaseOption配置類(lèi)
YAYBaseTagOption
的具體配置在 iOS 小組件 - 標(biāo)簽瀑布流Base組件抽取贞铣,APP業(yè)務(wù)重構(gòu)(一) 文中已經(jīng)介紹過(guò)了。
在通用的瀑布流多選器配置類(lèi) YAYTagMultipleChoiceOption
中主要添加了五個(gè)可自定義的選中配置沮明。
-
selectedItemTextColor
選中標(biāo)題顏色 -
selectedItemBackgourdColor
選中背景顏色 -
borderColor
邊框顏色 -
selectedBorderColor
選中邊框顏色 -
borderWidth
邊框大小
以下是配置類(lèi)源碼:
// 瀑布標(biāo)簽多選配置
import UIKit
class YAYTagMultipleChoiceOption: YAYBaseTagOption {
/// 選中標(biāo)題顏色
var selectedItemTextColor: UIColor = themeColor
/// 選中背景顏色
var selectedItemBackgourdColor: UIColor = themeColor.withAlphaComponent(0.08)
/// 邊框顏色
var borderColor: CGColor = themeColor.withAlphaComponent(0.12).cgColor
/// 選中邊框顏色
var selectedBorderColor: CGColor = themeColor.cgColor
/// 邊框大小
var borderWidth: CGFloat = 1
init(leftM: CGFloat = 24, rightM: CGFloat = 24, contentWidth: CGFloat = screenWidth) {
super.init()
self.leftM = leftM
self.rightM = rightM
self.contentWidth = contentWidth - leftM - rightM
cellClass = "YAYTagMultipleChoiceCell"
topM = 25
titleHeight = 22
itemHeight = 46
itemCorner = 23
minimumLineSpacing = 16
minimumInteritemSpacing = 16
fontSize = 16
fontWeight = .medium
itemLeftMargin = 24
itemRightMargin = 24
itemBackGroundColor = .white
itemTextColor = contentColor
}
}
BaseCell 元素
YAYTagMultipleChoiceCell
主要是根據(jù)多選器配置類(lèi)辕坝,自動(dòng)處理選中與未選中的樣式,綁定標(biāo)簽文本荐健。
// 瀑布標(biāo)簽多選cell
import UIKit
class YAYTagMultipleChoiceCell: YAYBaseTagCell {
// MARK: - bindData
override func tagOptionSet(option: YAYBaseTagOption) {
super.tagOptionSet(option: option)
guard let tagOption = option as? YAYTagMultipleChoiceOption else { return }
titleLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview().offset(tagOption.itemLeftMargin)
make.right.equalToSuperview().offset(-tagOption.itemRightMargin)
make.height.equalTo(option.titleHeight)
}
// 切換選中狀態(tài)
if isSelected {
titleLabel.textColor = tagOption.selectedItemTextColor
contentView.backgroundColor = tagOption.selectedItemBackgourdColor
contentView.layer.borderColor = tagOption.selectedBorderColor
contentView.layer.borderWidth = tagOption.borderWidth
contentView.layer.masksToBounds = true
}
else {
titleLabel.textColor = tagOption.itemTextColor
contentView.backgroundColor = tagOption.itemBackGroundColor
contentView.layer.borderColor = tagOption.borderColor
contentView.layer.borderWidth = tagOption.borderWidth
contentView.layer.masksToBounds = true
}
}
override func bindData(model: YAYBaseTagModel) {
super.bindData(model: model)
titleLabel.text = model.labelName
}
}
四酱畅、具體使用與效果
實(shí)際使用
類(lèi)似前文標(biāo)簽iOS 小組件 - 標(biāo)簽瀑布流Base組件抽取,APP業(yè)務(wù)重構(gòu)(一)江场、iOS 小組件 - 瀑布流單選器纺酸,技術(shù)設(shè)計(jì)與實(shí)現(xiàn)詳解(二)例子一樣,根據(jù)不同的 YAYTagMultipleChoiceOption
即可生成功能相同址否,樣式不同的多選器餐蔬,這里業(yè)務(wù)只做了一種樣式的瀑布流多選器,故沒(méi)有更多的使用例子佑附。
具體多選效果
實(shí)際運(yùn)行中樊诺,選夠了3個(gè)最低個(gè)數(shù)后,可進(jìn)行下一步音同。
最后词爬,又雙叒叕完成了一個(gè)開(kāi)箱即用的瀑布流多選器通用小組件,以后類(lèi)似的場(chǎng)景就可以直接引用該組件了权均。