IOS控制元件系列----使用UITableView實現網格佈局,自定義顯示列數
先放一引效果圖:
在IOS中達到類似Android中的GridLayout 通常是使用UIConlectionView,這個元件是平果公司已經封裝好的,直接實現相應的介面即可。不知道各位道友是否也曾想過用UItableView來擼一個這個東西,這可能會有一點偏執,但對於致力於提高自己的人來說,不安於現狀,死喜歡用各種自定義的東西來“折騰”自己也不失為一種方式。
我本人就比較喜歡在閒時擼一些小框架,右邊是我的github地址 點選這裡有驚喜
想要用UITableView來呈現網格佈局需要解決如下幾個問題。
問題一:預設的UITableView行數顯示的是一個,即顯示一個UITableViewCell ,這個東西,不知道各位有使用的時候有沒有注意到你不需要設定它的frame ,它也能完美在呆在UIUItabVlew中,只因平果公司為我們做好了,在設定單元格高度的時候,就固定了UITableViewCell的frame
在實現這個介面的時候 ,需要我們返回一個高度值
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
為了解決這個問題,我們曲線救國,既然UITableViewCell不然改變座標,那麼我們移動它內部的元素應該就行
UITableViewCell 個類擴充套件於UIView,看到UIView道友可能來興趣了,在IOS中有了UIView幾乎可以幹一切“壞事”
UIView有容乃大,
把UITableViewCell
問題二:列數的展示?
先說一個題外話,UITableView的複用機制,是針對UITableViewCell而言的,對UITableViewCell內容的子元素並未做到複用優化,這裡我也沒有想到想到優化方案,如果你想到了,請留下你的評論,我們一起交流下
回到主題 --列數的應該是可以定義的,那麼當列數設定好之後,相應的顯示的行數也應該要進行變化,計算式子如下:
行數 = (資料列表的長度 -1)./ 列數 + 1
本案例程式碼為:
rowNum = (dataList.count - 1) / colNum + 1 } //implements protocol func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return rowNum }
問題三:之前使用UITableView時,將資料打到UITableViewCell上時,是按行進行繫結的,現在是一行顯示多列資料就需要重寫這個介面
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
使其在資料列表中取到正確索引的資料
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : UITableViewCell = UITableViewCell()
for i in 0..<colNum {
if indexPath.row * colNum + i >= self.dataList.count {
break;
}
let view : TestView = TestView()
view.label.text = dataList[indexPath.row * colNum + i]
view.label.textColor = UIColor.green
view.frame = CGRect.init(x: i * 90 + 10, y: 0, width: 60, height: 40)
cell.addSubview(view)
}
return cell
}
一些該丟出去的屬性,這裡未做過多說明,相信你完全有這個能力將其美化,本案例權當拋磚引玉,介紹下設計思路:
完整程式碼如下:
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
lazy var tableView : UITableView = {() -> UITableView in
var tabView : UITableView = UITableView.init(frame: CGRect.init(x: 0, y: 40, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
return tabView
}()
lazy var dataList : Array<String> = {() -> Array<String> in
var arr : Array<String> = Array<String>()
return arr
}()
let colNum : Int = 4
var rowNum : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
initView()
}
func initView() {
tableView.delegate = self
tableView.dataSource = self
self.view.addSubview(tableView)
//初始化資料
for i in 0..<13{
dataList.append(String.init(format: "%d", i))
}
rowNum = (dataList.count - 1) / colNum + 1
}
//implements protocol
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return rowNum
}
//implements protocol
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
//implements protocol
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : UITableViewCell = UITableViewCell()
for i in 0..<colNum {
if indexPath.row * colNum + i >= self.dataList.count {
break;
}
let view : TestView = TestView()
view.label.text = dataList[indexPath.row * colNum + i]
view.label.textColor = UIColor.green
view.frame = CGRect.init(x: i * 90 + 10, y: 0, width: 60, height: 40)
cell.addSubview(view)
}
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}