UX的核心是在幫助用戶理解應用的同時提供更愉悅的使用體驗
環(huán)境:
- Xcode 8.3.1
- Swift 3
目錄
- demo
- 關鍵點
- Storyboard的設置
- 代碼
- 總結
(簡書不支持頁內(nèi)跳轉(zhuǎn),這是個雞肋目錄 = =)
demo
UIScrollView
及其子類UITableView
, UICollectionView
是app里經(jīng)常用到的視圖組件蘸鲸。iOS自帶的反彈特性提供了不錯的反饋信息。結合實現(xiàn)滑動相關的delegate吆视,我們可以構建出多種交互反饋,給用戶提供更明白又眼前一亮的效果酥宴。
以下展示一個通過滑動scroll view,與標題圖片進行聯(lián)動反饋的例子您觉。這個反饋效果在很多App里都很普遍拙寡。其實在大半年前我就寫過一篇博客分享同樣效果的實現(xiàn)方法。后面積累了些項目經(jīng)驗后琳水,發(fā)現(xiàn)有更簡潔且穩(wěn)妥的實現(xiàn)方式肆糕,同時開始轉(zhuǎn)用Swift。在此推薦一波Swift在孝,相對OC而言诚啃,Swift提供了更多實用的語言特性,寫法也比OC簡潔不少私沮。
<p id="keys"></p>
關鍵點
-
UIImageView:
-
height
屬性跟隨UIScrollView
的滑動而線性變化 -
contentMode
屬性設定為UIViewContentModeScaleAspectFill
-
-
UIScrollView:
- 初始
contentInset
屬性的height
設定為UIImageView
對象的height
- 初始
<p id="storyboard"></p>
Storyboard的設置
雖然標題圖片與scroll view孰上孰下都會是同樣的視覺效果始赎,不過要想標題圖片可以點擊,建議將其image view放在上層仔燕,如圖:
為了使例子更清楚造垛,這里使用table view,scroll view和其他子類同理
設定Auto Layout的約束:
- image view: 上晰搀、左五辽、右貼邊,并添加高度約束外恕,數(shù)值隨意杆逗,反正需要在代碼初始化并聯(lián)動更改
- table view: 上、下鳞疲、左罪郊、右貼邊
具體如圖:
需要注意的是,image view需要設定:
-
contentMode = .scaleAspectFill
建丧,讓image view根據(jù)最短一邊來等比放大和縮放 isUserInteractionEnabled = true
-
clipsToBounds = true
(不設定的話會出現(xiàn)即使image view高度為0但image依舊會展示的效果) - 這里image view會擋住下面table view的cell的設計排龄。可以在設計時先把table view放在上層,完了再放回下面橄维,拖一下鼠標的事情
<p id="code"></p>
代碼
最開心的進入代碼的時刻來了~慣常把image view和table view的引用拉到view controller里來尺铣。同時,把image view的height約束也拉過來:
var bannerImageViewDefaultHeight: CGFloat {
return UIScreen.main.bounds.width * 1 / 2
}
@IBOutlet weak var bannerImageView: UIImageView!
@IBOutlet weak var tableView: UITableView! {
didSet {
tableView.delegate = self
tableView.dataSource = self
tableView.estimatedRowHeight = 40.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.contentInset = UIEdgeInsetsMake(bannerImageViewDefaultHeight, 0.0, 0.0, 0.0)
}
}
@IBOutlet weak var bannerImageViewHeightConstraint: NSLayoutConstraint! {
didSet {
bannerImageViewHeightConstraint.constant = bannerImageViewDefaultHeight
}
}
以上代碼的幾個要點:
- 這里想要標題圖片的高度是屏幕寬度的一半争舞,于是利用computed屬性
bannerImageViewDefaultHeight
返回 - 設定標題圖片的高度約束
bannerImageViewHeightConstraint
凛忿。為什么是使用約束更改高度?下文會詳解說明 - 設定table view的
contentInset
為上端inset為初始標題圖片的高度竞川,好讓table view的內(nèi)容剛好在標題圖片下方開始展示 -
didSet
里的代碼在對象引用設定后會調(diào)用店溢,在didSet
之前,我們一般在viewDidLoad
里設定視圖組件的屬性委乌。使用didSet
可以使設定代碼與對應的組件更緊湊床牧,便于閱讀。關于Swift的不同屬性的解釋請戳此 -
estimatedRowHeight
的值影響table view對content高度的初步計算遭贸,從而影響右側(cè)scrolling indicator的精確度戈咳;rowHeight = UITableViewAutomaticDimension
是讓table view開啟利用Auto Layout計算layout的功能,據(jù)說蘋果在iOS 11里對table view進行了優(yōu)化壕吹,rowHeight
不再需要人手設定而隱式開啟使用Auto Layout著蛙。具體有待考證。
設定滑動的聯(lián)動反饋效果:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
bannerImageViewHeightConstraint.constant = offsetY < 0.0 ? -offsetY : 0.0
}
超級實用的scrollViewDidScroll(_:)
排上用場啦~scroll view往下滑動的contentOffset.y
是減小耳贬,當添加大于0的上端inset踏堡,長度為bannerImageViewDefaultHeight
時,初始的contentOffset.y
會是-bannerImageViewDefaultHeight
咒劲。
這里說下為什么改約束而不是直接改image view的frame呢顷蟆?我曾經(jīng)也習慣直接改frame,簡單快捷缎患,不需要額外拉一條約束的引用進入view controller慕的。但在我看完realm的一篇分享之后,關于之前遇到的view的一些奇怪行為恍然大悟挤渔。
簡單來說就是肮街,在iOS的定義里,Auto Layout相當于一系列視圖組件的布局規(guī)則判导。當我們在代碼里直接更改frame時嫉父,我們是在Auto Layout之外進行操作。那么問題來了眼刃,系統(tǒng)的一些特定事件會觸發(fā)布局系統(tǒng)重新讀取我們設定在視圖組件上的一系列約束绕辖,
這就意味著我們更改的frame會被重置,而這也許不是我們想要的結果擂红。因此我現(xiàn)在的偏好是仪际,如果用了Auto Layout做布局,代碼里針對view的布局更改甚至一些動畫都通過修改約束來進行,這樣當特定事件出現(xiàn)時树碱,視圖組件的布局會維持原樣肯适。那么,有哪些系統(tǒng)特定事件呢成榜?如下:
- 鍵盤的彈出與收回
- 手機豎屏與橫屏的切換
- 視圖組件或其父視圖組件調(diào)用
layoutIfNeeded()
時 (其實這是根本)
<p id="conclusion"></p>
總結
scrollViewDidScroll(_:)
是可以實現(xiàn)很多有趣的滑動反饋的開始框舔。對不同應用,應該根據(jù)實際來實現(xiàn)合適的用戶體驗反饋赎婚。
完整代碼已上傳至個人Github刘绣。傳送請戳此