當 table view 或 collection view 進入編輯模式時顯示不同樣式的 cell

我們時常在 iOS App 看到點選 Edit 按鈕進入編輯模式的畫面設計,比方下圖的 Clock App,點選 Edit 後 cell 會出現刪除跟調整順序的按鈕。

不過上圖還有個特別的設計,進入編輯模式時 cell 的內容也改變了,為了節省空間,它的時間不見了。這是怎麼做到的呢 ?

接下來我們將示範實作的方法,關鍵在讓 table view 或 collection view 在編輯模式時顯示不同樣式的 cell,在正常模式顯示有時間的 cell,在編輯模式拿掉時間。

App 畫面設計

table view controller 的類別為繼承 UITableViewController 的 TimeTableViewController,cell 的類別為繼承 UITableViewCell 的 TimeTableViewCell。

TimeTableViewCell

class TimeTableViewCell: UITableViewCell {
static let reuseIdentifier = "\(TimeTableViewCell.self)"

@IBOutlet weak var locationLabel: UILabel!
@IBOutlet weak var timeLabel: UILabel!

override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}}

TimeTableViewController

利用 TimeZone.knownTimeZoneIdentifiers 找出世界各地的時區代號,在表格顯示城市名跟時間。(ps: 以下範例不會自動更新時間,因為它不是此篇文章的重點)

class TimeTableViewController: UITableViewController {

let timeZoneIdentifiers = TimeZone.knownTimeZoneIdentifiers.filter {
$0.contains("/") }
let dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = .short
return dateFormatter
}()

override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = editButtonItem
}

// MARK: - Table view data source

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return timeZoneIdentifiers.count
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TimeTableViewCell.reuseIdentifier, for: indexPath) as! TimeTableViewCell
let id = timeZoneIdentifiers[indexPath.row]
let city = id.components(separatedBy: "/")[1]
cell.locationLabel.text = city
dateFormatter.timeZone = TimeZone(identifier: id)
cell.timeLabel.text = dateFormatter.string(from: .now)
return cell
}
}

執行 App

點選 Edit 進入編輯模式,左邊出現刪除按鈕。

不過因為縮排的關係,右邊的時間有的會變成 …。接下來我們將模仿 iOS 的 Clock App,在編輯模式時將時間隱藏。

在編輯模式切換時更新表格

當畫面進入或結束編輯模式時,會觸發 UIViewController 的 setEditing(_:animated:),因此我們可覆寫它,在裡面呼叫 reloadData 更新表格。

override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
tableView.reloadData()
}

在編輯模式時將時間隱藏

檢查 isEditing 判斷是否處於編輯模式,isEditing true 時將時間隱藏。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TimeTableViewCell.reuseIdentifier, for: indexPath) as! TimeTableViewCell
let id = timeZoneIdentifiers[indexPath.row]
let city = id.components(separatedBy: "/")[1]
cell.locationLabel.text = city
dateFormatter.timeZone = TimeZone(identifier: id)
if isEditing {
cell.timeLabel.isHidden = true
} else {
cell.timeLabel.text = dateFormatter.string(from: .now)
cell.timeLabel.isHidden = false
}

return cell
}

Cool,現在正常模式跟編輯模式的表格長不一樣了,只有正常模式會顯示時間。

其它範例參考

Apple 的 Today App,範例裡定義 ReminderDetailViewDataSource & ReminderDetailEditDataSource,當 table 在正常模式時 data source 是 ReminderDetailViewDataSource,當 table 在編輯模式時 data source 是 ReminderDetailEditDataSource。

--

--

彼得潘的 iOS App Neverland
彼得潘的 Swift iOS App 開發問題解答集

彼得潘的iOS App程式設計入門,文組生的iOS App程式設計入門講師,彼得潘的 Swift 程式設計入門,App程式設計入門作者,http://apppeterpan.strikingly.com