UIScrollView是iOS開(kāi)發(fā)中經(jīng)常用到的UI控件,像圖片輪播之類(lèi)的效果都可以用UIScrollView來(lái)實(shí)現(xiàn),當(dāng)然輪播什么的網(wǎng)上有很多教程了,我就不多說(shuō)了。今天主要講三個(gè)跟交互有關(guān)的效果(稍微有點(diǎn)標(biāo)題黨啊,其實(shí)也沒(méi)有多進(jìn)階……),也不是直接用的UIScrollView,而是它的子類(lèi)UITableView和UIWebView。先看一下效果圖吧,都來(lái)自我自己的項(xiàng)目:
先看第一個(gè),是個(gè)挺常用的效果。列表上面是三個(gè)欄目按鈕和輪播圖片,向上滾動(dòng)時(shí),按鈕和圖片一起向上,按鈕周邊區(qū)域顏色漸變,然后在到指定位置時(shí)(這里是蓋住導(dǎo)航欄之后)按鈕停住不動(dòng),周邊顏色也完全變成導(dǎo)航欄的顏色,列表數(shù)據(jù)還可以繼續(xù)滾動(dòng)。這個(gè)要怎么實(shí)現(xiàn)呢?其實(shí)也挺簡(jiǎn)單,重點(diǎn)是 contentInset
這個(gè)屬性。這個(gè)屬性是UIScrollView的,用來(lái)指定內(nèi)容邊界,UITableView繼承自UIScrollView,當(dāng)然也含有這個(gè)屬性。
tableView.contentInset.top = tableViewInsetTop
tableViewInsetTop
是我定義的一個(gè)常量,這句代碼指定tableView里的實(shí)際內(nèi)容離tableView整個(gè)frame的頂部距離為tableViewInsetTop
。這段距離用來(lái)放圖片和欄目按鈕。然后就是在 scrollViewDidScroll
這個(gè)委托方法中做一點(diǎn)處理:
func scrollViewDidScroll(scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
if -offsetY > menuBtnH - barHeight {
//按鈕未到指定位置前,圖片與按鈕都跟隨滑動(dòng)
menuBtnsView.frame.origin.y = -offsetY - menuBtnH + topBorder
imageSlider.frame.origin.y = -(TableViewInsetTop + offsetY) + focusImageY
//透明度漸變
let alphaValue = 1 + (offsetY + menuBtnH) / (focusImageH/2)
menuBtnsView.backgroundColor = UIColor.navigationBarColor(alphaValue)
} else if menuBtnsView.frame.origin.y != statusHeight {
//防止滑動(dòng)過(guò)快導(dǎo)致控件停留在錯(cuò)誤的位置
menuBtnsView.frame.origin.y = statusHeight
imageSlider.frame.origin.y = -focusImageH
menuBtnsView.backgroundColor = UIColor.navigationBarColor()
}
}
稍微說(shuō)明一下,offsetY
是UITableView里的內(nèi)容在Y軸上的偏移量。因?yàn)橹霸O(shè)置了contentInset
,所以這個(gè)offsetY
一開(kāi)始是等于-TableViewInsetTop
的。menuBtnH
是欄目按鈕的高,barHeight
是導(dǎo)航欄的高。我要做的效果是欄目按鈕得蓋住導(dǎo)航欄,所以按鈕要在-offsetY = menuBtnH - barHeight
的時(shí)候才會(huì)停下。感興趣的同學(xué)可以看一下我單獨(dú)為這個(gè)效果寫(xiě)的一個(gè)簡(jiǎn)單Demo,clone下來(lái)自己跑一下,琢磨琢磨應(yīng)該就明白了。
第二個(gè)效果是拉出一個(gè)按鈕,按鈕的背景色也是由淺入深漸變,拉出來(lái)之后按鈕就停在頂部,然后刷新圖標(biāo)(旋轉(zhuǎn)小菊花)會(huì)在按鈕下面顯示。這個(gè)其實(shí)也很簡(jiǎn)單,主要就是在完全拉出按鈕之后改變contentInset
:
//Mark: - Table view delegate(下拉顯示提問(wèn)按鈕)
override func scrollViewDidScroll(scrollView: UIScrollView) {
let offsetY = -scrollView.contentOffset.y
if offsetY < maxH {
//按鈕淡入效果
askBtn.askLabel.alpha = offsetY/maxH
return
}
if btnShow {
//按鈕停留頂部
askBtn.frame.origin.y = -offsetY
return
}
tableView.contentInset.top = maxH
self.refreshControl = refreshCtrl
askBtn.askLabel.alpha = 1
btnShow = true
}
沒(méi)太多可說(shuō)的,繼續(xù)第三個(gè)效果吧。第三個(gè)效果就不是TableView了,而是個(gè)WebView,效果是向上滑動(dòng)時(shí)隱藏底欄,向下時(shí)顯示底欄。重點(diǎn)是判斷WebView的滑動(dòng)方向:
extension WebViewCtrl: UIScrollViewDelegate {
//判斷當(dāng)前是向上還是向下滑動(dòng)
func scrollViewDidScroll(scrollView: UIScrollView) {
newY = scrollView.contentOffset.y
if newY > oldY {
scrollDirection = .Up
} else if oldY > newY {
scrollDirection = .Down
}
//更新y軸偏移量
oldY = newY
}
}
scrollDirection
的類(lèi)型是自己定義的一個(gè)枚舉:
enum ScrollDirection {
case Up
case Down
case None
}
具體的實(shí)現(xiàn)可以看看我之前寫(xiě)的這個(gè)CustomWebView,原理是一樣的,只不過(guò)把底欄換成了收藏按鈕。
嗯,有什么問(wèn)題歡迎評(píng)論。