UIKit實作100#2-自訂表格cell
自訂表格cell質感看起來會好一些
使用UITableViewController與UITableViewDifableDataSource來建立表格。
新增TableViewController
新增檔案後,都會有預設的storyboard跟關聯swift檔案,把這兩個刪除,然後另外新增一個storyboard跟關聯swift檔案。
is Initial View Controller記得要打勾
才能會是第一個畫面
新增關聯檔案
新增檔案
檔名:RestaurantTableViewController
選擇Cocoa Touch Class,後按Next
Subclass of 要撰”UITableViewController”
接下來都預設
成功新增後會出現新增檔案的內容
裡面的程式是我們在使用TableViewController時可能會用到的
新增的TableViewController跟新增的檔案做聯結
數字3按下去就會看到剛剛新增的檔案,按下去就聯結了。
如果沒有你要的檔案,可能Subclass of選錯了。
cell設定Identifier名稱為datacell
要使用cell都要設Identifier
如果要選定某個元表,選數字1的部份會比較好選,不容易選錯。
Style 要選擇 Basic
接下來要寫程式了…
點開 RestaurantTableViewController.swift
點開後會看到這二個func
因為要使用UITableViewDiffableDataSoure
所以就不用用到這二個func了
可以先刪除或註解掉
宣告變數
宣告變數來存放表格資料
放在viewDidLoad()上面
var restaurantNames = ["Cafe Deadend", "Homei", "Teakha", "Cafe Loisl", "Petite Oyster", "For Kee Restaurant", "Po's Atelier", "Bourke Street Bakery", "Haigh's Chocolate", "Palomino Espresso", "Upstate", "Traif", "Graham Avenue Meats And Deli", "Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia", "Royal Oak", "CASK Pub and Kitchen"]
宣告列舉
因為沒有了上面那兩個方法,無法告訴程式要放什麼資料,
所以我們要使用NSDiffableDataSourceSnapshot
要使用就要宣告列舉
enum Section {
case all
}
寫在restaurantNames變數的上方
這個列舉是用來定義一個新的 Section 型別。
只有一個case是因為表格只有一個區塊、
而case命名為all,表示為所有的資料。
建立 UITableViewDiffableDataSoure的實列
程式碼可以寫在viewDidLoad()底下
func configureDataSource() -> UITableViewDiffableDataSource<Section, String>{
let cellIdentifier = "datacell"
let dataSource = UITableViewDiffableDataSource<Section, String>(
tableView: tableView,
cellProvider: { tableView, indexPath, restaurantNames in
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
cell.textLabel?.text = restaurantNames
cell.imageView?.image = UIImage(named: "restaurant")
return cell
}
)
return dataSource
}
第一行是函數宣告方式
->這個符號表示回傳
後面接著的是回傳物件的型別
configureDataSource是這個函數的名稱
所以是建立了一個名為configureDataSource()的函數,
回傳一個UITableViewDiffableDataSource<Section, String>的實例。
以上是資料來源的函數
使用資料來源的函數-lazy修飾器
資料來源的函數寫好了,接著就要使用它。
lazy var dataSource = configureDataSource()
如果沒有加上”lazy”會出現錯誤訊息:Cannot use instance member ‘configureDataSource’ within property initializer; property initializers run before ‘self’ is available
更新viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = dataSource
var snapshot = NSDiffableDataSourceSnapshot<Section, String>()
snapshot.appendSections([.all])
snapshot.appendItems(restaurantNames, toSection: .all)
dataSource.apply(snapshot, animatingDifferences: false)
}
現在測試一下
因為只有放一張照片,所以只有一張照片。
放不同的照片
新增新的陣列
var restaurantImages = ["Cafe Deadend", "Homei", "Teakha", "Cafe Loisl", "Petite Oyster", "For Kee Restaurant", "Po's Atelier", "Bourke Street Bakery", "Haigh's Chocolate", "Palomino Espresso", "Upstate", "Traif", "Graham Avenue Meats And Deli", "Waffle & Wolf", "Five Leaves", "Cafe Lore", "Confessional", "Barrafina", "Donostia", "Royal Oak", "CASK Pub and Kitchen"]
因為是陣列,所以要修改一下程式碼。
把
cell.imageView?.image = UIImage(named: "restaurant")
改成
cell.imageView?.image = UIImage(named: self.restaurantImages[indexPath.row])
設計Prototype Cell
更改cell樣式-Custom
上面在設定cell的樣式是用 Basic
如果要自訂的話要用 Custom
變更cell高度
拉出元件放到cell內
先拉一個圖片物件
大小為120*120
到它的屬性檢閱器,把 「Content Mode」改為 Aspect Fill
接著拉出三個Label
分別作用:
Name-餐廳名稱
Location-餐廳位置
Type-餐廳類型
屬性檢閱器有一些設定可以改
將三個label選取起來,要把它們群組起來
在佈局列中點選 Embed in 按鈕
選取「Stack View」
接著再跟圖片做一次群組
寫程式。。。。
為cell建立類別
與cell做聯結
宣告Outlet變數
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var locationLabel: UILabel!
@IBOutlet weak var typeLabel: UILabel!
@IBOutlet weak var thumbnailImageView: UIImageView!
更新cell提供者
找出這一行程式碼:
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
改成
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! RestaurantTableViewCell
接著
cell.textLabel?.text = restaurantNames
cell.imageView?.image = UIImage(named: self.restaurantImages[indexPath.row])
換成
cell.nameLabel.text = restaurantNames
cell.thumbnailImageView.image = UIImage(named: self.restaurantImages[indexPath.row])
測試後發現高度不能調高
剛剛我是從storyboard做高度的更改。。。無效
現在我用程式改高:
tableView.rowHeight = 140
寫在viewDidLoad()裡面
就可以了
將縮圖變成圓形
- 背景顏色(Background Color)
- 邊框(Border)
- 邊框寛度(Border Width)
- 陰影顏色(Shadow Color)
- 陰影寛度(Width)
- 透明度(Opacity)
- 圓角半徑(Corner Radius)
以介面建構器來修改
加號按下去之後:
“key Path” 改成 “cornerRadius” 然後Enter
Type 屬性選 Number
最後值設定為 20
另外記得 Clip to Bounds 要打勾
這個功能是可以該圖形修為圓角
也可以用程式修改圖片
@IBOutlet weak var thumbnailImageView: UIImageView!{
didSet{
thumbnailImageView.layer.cornerRadius = 20
thumbnailImageView.clipsToBounds = true
}
}
didSet就是swift的屬性觀察者。
在didSet區塊中,每次設定屬性值時會被呼叫。
使用深色模式測試APP
將 Location 跟 Type 顯示上去
var restaurantLocations = ["Hong Kong", "Hong Kong", "Hong Kong", "Hong Kong", "Hong Kong", "Hong Kong", "Hong Kong", "Sydney", "Sydney", "Sydney", "New York", "NewYork", "New York", "New York", "New York", "New York", "New York", "London", "London", "London", "London"]
var restaurantTypes = ["Coffee & Tea Shop", "Cafe", "Tea House", "Austrian / Causual Drink", "French", "Bakery", "Bakery", "Chocolate", "Cafe", "American / Seafood", "American", "American", "Breakfast & Brunch", "Coffee & Tea", "Coffee & Tea", "Latin American", "Spanish", "Spanish", "Spanish", "British", "Thai"]
另外,加上這兩行
cell.locationLabel.text = restaurantLocations[indexPath.row]
cell.typeLabel.text = restaurantTypes[indexPath.row]
這樣就好看了
移除cell分隔線
在viewDidLoad()裡加入下行程式:
tableView.separatorStyle = .none