簡要
這次要來完成上方篩選的細節
上次只有實作簡單版的collectionView
但要仔細觀察他每個字其實都有自適應寬度
自適應
在很多地方都用得到
今天就來研究 Swfit 自適應寬度
collectionView
要控制cell大小除了之前有提過的
layout.itemSize = CGSize(width: 100, height: 30)
要做更詳細的控制每個index row
可以使用collectionViewLayout
做控制
回傳CGSize
改變每一個cell
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize{
var cellSize = CGSize()
return cellSize
}
這裡很重要*3
這不像是OC
直接將func
打好就可以控制
記得宣告頂部的UICollectionViewDelegateFlowLayout
才可以雙劍合併 你的cell
才會改變
如果下沒作動
記得看一下有沒有宣告
class HomeViewController: UICollectionViewDelegateFlowLayout
我這邊將上面分類的文字都先用一個陣列儲存好
畢竟沒api直接寫死就可以了
var filterTitleArr: Array<String> = []
filterTitleArr = ["分類", "價格範圍", "外送費上限", "飲食限制"]
這邊開始就可以注意到
他的篩選有五個文字
並且有長有短
所以我們需要幫他們各自測量大小
這邊有一個func
可以讓你帶入 font
以及maxSize
自動回傳
最大的高度
以及長度
// MARK: - Custom Methods
func textSize(text : String , font : UIFont , maxSize : CGSize) -> CGSize{
return text.boundingRect(with: maxSize, options: [.usesLineFragmentOrigin], attributes: [NSAttributedString.Key.font : font], context: nil).size
}
接下來回去剛剛的collectionViewLayout
將func
加入到裡面
並且把該填入的質都帶進去
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var cellSize = CGSize()
let textFont = UIFont.systemFont(ofSize: 17)
let textString = filterTitleArr[indexPath.item]
let textMaxSize = CGSize(width: 240, height: CGFloat(MAXFLOAT))
let textLabelSize = self.textSize(text:textString , font: textFont, maxSize: textMaxSize)
//+40 是右方icon寬度 + 其他設定
//如果你是單純文字的話不用加
cellSize.width = textLabelSize.width + 40
//高度固定
cellSize.height = 30
return cellSize
}
cellForItemAtindexPath
裡面記得把剛剛的文字
也放進去
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:HomeCell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath)
as! HomeCell
//文字
cell.textLabel.text = filterTitleArr[indexPath.item]
//圖片
cell.iconImg?.image = UIImage.init(named: "down")
}
簡單Demo
看起來好像可以了
但是前方好像還有
一個設定icon
跟大家特別不一致
沒label
圖片大小
也不同
原APP
我在想說要不要乾脆count
直接+1
在index item == 0
的地方直接addSubView
感覺好像可以 來實做看看
collectionViewLayout
第一個按鈕是正圓形
所以將其設定為正方形
即可
剩餘不變
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var cellSize = CGSize()
if indexPath.item == 0 {
cellSize.width = 30
}else{
let textFont = UIFont.systemFont(ofSize: 17)
let textString = filterTitleArr[indexPath.item - 1]
let textMaxSize = CGSize(width: 240, height: CGFloat(MAXFLOAT))
let textLabelSize = self.textSize(text:textString , font: textFont, maxSize: textMaxSize)
cellSize.width = textLabelSize.width + 40
}
cellSize.height = 30
return cellSize
}
numberOfItemsInSection
count
比剛剛還多1
為了放置
前方icon
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
cellForItemAtindexPath
這裡的想法是直接接之前的
文字Label
跟 icom
都隱藏
並且加入單純的設定icon
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:HomeCell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath)
as! HomeCell
cell.backgroundColor = UIColor.init(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.1)
cell.clipsToBounds = true
cell.layer.cornerRadius = cell.frame.height/2
if indexPath.item == 0 {
cell.textLabel.isHidden = true
cell.iconImg.isHidden = true
let titleImg = UIImageView()
titleImg.frame = CGRect.init(x: cell.frame.width*0.3, y: cell.frame.height*0.3, width: cell.frame.width*0.4, height: cell.frame.height*0.4)
titleImg.image = UIImage.init(named: "settings")
cell.addSubview(titleImg)
}else{
cell.textLabel.isHidden = false
cell.iconImg.isHidden = false
cell.textLabel.text = filterTitleArr[indexPath.item - 1]
cell.iconImg?.image = UIImage.init(named: "down")
}
return cell
}
Demo
哇 是不是完成了
看似美好 我就在想
這樣會不會他每次都add
一個image
出來
越想越不對
立刻把 titleImg.alpha = 0.1
這樣如果重複新增的話會越來越深
結果果然越變越深
這樣會造成我的記憶體爆掉
不太行
決定把原來的客製化HomeCell
做修改
使用Stack View把他們三個選成一個群組
原先
新增stackView
將三個元件新增進來
並且把 title icon
固定 1:1比例尺
新增進去
再來使用Hidden
來控制是否要出現
Stack View
的好處就是會像
Android
的gone
一樣
Hidden
時位置也會消失
不會留空白在原地
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:HomeCell = collectionView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath)
as! HomeCell
cell.backgroundColor = UIColor.init(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.1)
cell.clipsToBounds = true
cell.layer.cornerRadius = cell.frame.height/2
if indexPath.item == 0 {
cell.textLabel.isHidden = true
cell.iconImg.isHidden = true
cell.titleImg.isHidden = false
}else{
cell.textLabel.isHidden = false
cell.iconImg.isHidden = false
cell.titleImg.isHidden = true
cell.textLabel.text = filterTitleArr[indexPath.item - 1]
}
return cell
}
Demo
大功告成