编译:伯乐在线 - BEASTQ
如需转载,发送「转载」二字查看说明
摘要
Kersten Broich 和 Justus Gandhi 只使用了一个 tableview 来展示三种形式的 UI 界面。方法看起来很简单,UI 切换效果也非常漂亮。
在我们的一次评估会议中,我们面临一个累赘、高代价的挑战,这会让视图控制器变得臃肿。
面临的挑战是,不使用导航视图控制器栈的前提下,创建一个登录和注册的表格。视图中只有标签、按钮和文本输入框,所有控件都需要添加位移动画。这防止用户丢失已经键入文本框的任何凭证。
入门
虽然我们已经在考虑创建一个复杂的状态机,使用动态布局来回切换、隐藏显示恰当的视图。我们想到了一个有趣的想法,使用一个 UITableView 并让其动画 API 为我们完成所有工作。UITableView 看深一些,发现他们实际上是相当灵活的。
我们开始把视图分割成独立的单元,如分隔符、文本框、按钮等,每个单元是一个 UITableViewCell。同样,我们创建一个 Swift Enumeration,声明每个单元格的标识符。
enumAuthCellType: String{
caseHeadline
caseEmailTextField
caseNameTextField
casePasswordTextField
caseLoginButton
caseSeparator
}
然后我们把视图的每个可能状态(例如登录或注册)分解成有单个组成的列表。举个例子,这里是两个状态的简化版本。
let loginState= [
.Headline,
.Separator,
.EmailTextField,
.PasswordTextField,
.LoginButton
]
letregisterState= [
.EmailTextField,
.NameTextField,
.PasswordTextField,
.LoginButton
]
动画状态切换
然后我们考虑如何在视图之间来回动画。UITableView 公开了一些简单的 API,用于平缓插入、删除带索引路径数组标识的单元格:
func insertRowsAtIndexPaths(_indexPaths: [NSIndexPath]withRowAnimationanimation: UITableViewRowAnimation)
func deleteRowsAtIndexPaths(_indexPaths: [NSIndexPath],withRowAnimationanimation: UITableViewRowAnimation)
所以,我们必须取出即将添加的单元格的 NSIndexPaths,以及在两个状态间消失的视图的索引。
假设用户在登录视图上启动,然后发现自己没有账户,并按下按钮注册新账户。
在这种情况下,必须删除索引 0 和 1 的 .Headline 和 .Separator,并且在索引 1 的位置添加新单元格 .NameTextField。集合更改如下:
let addedIndexes= [1]
letremovedIndexes= [0,1]
改变状态后,必须转换为 NSIndexPaths 数组,并传递到前面提到的 UITableView 方法来触发状态改变动画。
自动生成集合改变
自然想到的解决办法是,在视图状态转换间,指定插入和删除行的 NSIndexPaths 数组。但我们寻找一个更加可维护的解决方案,旨在更少的手工工作。
自动生成这些变更集不是个琐碎问题。解决方案的关键是旨在解决最长公共子序列问题(LCS)的算法。幸运的是,我们在 github 上找到了著名的 SwiftLCS 库(https://github.com/Frugghi/SwiftLCS),它可以帮助你着手识别两个结合的变更集。
我们最终基于 SwiftLCS 的解决方案如下:
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 与现有工具一起使用的可能性。
看完本文有收获?请分享给更多人
关注「 iOS大全 」,提升iOS技能