摘要
Kersten Broich 和 Justus Gandhi 只使用了一個 tableview 來展示三種形式的 UI 介面。方法看起來很簡單,UI 切換效果也非常漂亮。
在我們的一次評估會議中,我們面臨一個累贅、高代價的挑戰,這會讓檢視控制器變得臃腫。
面臨的挑戰是,不使用導航檢視控制器棧的前提下,建立一個登入和註冊的表格。檢視中只有標籤、按鈕和文字輸入框,所有控制元件都需要新增位移動畫。這防止使用者丟失已經鍵入文字框的任何憑證。
入門
雖然我們已經在考慮建立一個複雜的狀態機,使用動態佈局來回切換、隱藏顯示恰當的檢視。我們想到了一個有趣的想法,使用一個 UITableView 並讓其動畫 API 為我們完成所有工作。UITableView 看深一些,發現他們實際上是相當靈活的。
我們開始把檢視分割成獨立的單元,如分隔符、文字框、按鈕等,每個單元是一個 UITableViewCell。同樣,我們建立一個 Swift Enumeration,宣告每個單元格的識別符號。
1 2 3 4 5 6 7 8 9 |
enum AuthCellType: String { case Headline case EmailTextField case NameTextField case PasswordTextField case LoginButton case Separator } |
然後我們把檢視的每個可能狀態(例如登入或註冊)分解成有單個組成的列表。舉個例子,這裡是兩個狀態的簡化版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
let loginState = [ .Headline, .Separator, .EmailTextField, .PasswordTextField, .LoginButton ] let registerState = [ .EmailTextField, .NameTextField, .PasswordTextField, .LoginButton ] |
動畫狀態切換
然後我們考慮如何在檢視之間來回動畫。UITableView 公開了一些簡單的 API,用於平緩插入、刪除帶索引路徑陣列標識的單元格:
1 2 3 4 |
func insertRowsAtIndexPaths(_ indexPaths: [NSIndexPath] withRowAnimation animation: UITableViewRowAnimation) func deleteRowsAtIndexPaths(_ indexPaths: [NSIndexPath], withRowAnimation animation: UITableViewRowAnimation) |
所以,我們必須取出即將新增的單元格的 NSIndexPaths,以及在兩個狀態間消失的檢視的索引。
假設使用者在登入檢視上啟動,然後發現自己沒有賬戶,並按下按鈕註冊新賬戶。
在這種情況下,必須刪除索引 0 和 1 的 .Headline 和 .Separator,並且在索引 1 的位置新增新單元格 .NameTextField。集合更改如下:
1 2 3 |
let addedIndexes = [1] let removedIndexes = [0, 1] |
改變狀態後,必須轉換為 NSIndexPaths 陣列,並傳遞到前面提到的 UITableView 方法來觸發狀態改變動畫。
自動生成集合改變
自然想到的解決辦法是,在檢視狀態轉換間,指定插入和刪除行的 NSIndexPaths 陣列。但我們尋找一個更加可維護的解決方案,旨在更少的手工工作。
自動生成這些變更集不是個瑣碎問題。解決方案的關鍵是旨在解決最長公共子序列問題(LCS)的演算法。幸運的是,我們在 github 上找到了著名的 SwiftLCS 庫,它可以幫助你著手識別兩個結合的變更集。
我們最終基於 SwiftLCS 的解決方案如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
func transitionToViewState(newState: AuthViewState) { let diff = currentState.diff(newState) tableView?.beginUpdates() tableView?.insertRowsAtIndexPaths(diff.addedIndexes, withRowAnimation: .Fade) tableView?.deleteRowsAtIndexPaths(diff.removedIndexes, withRowAnimation: .Fade) tableView?.endUpdates() } |
該 transitionToViewState 方法可以與 AuthCellType 元素陣列呼叫,表檢視會自動動畫到對應的狀態。
結論
這個例子可能不會適合每個人。對我們來說,它更多的是提醒我們,始終重新思考如何使用 UIKit 與現有工具一起使用的可能性。
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!
任選一種支付方式