閑來(lái)無(wú)事時(shí)讀到移動(dòng)開(kāi)發(fā)前線的這篇文章充甚,里面介紹了一些小紅書開(kāi)發(fā)者的相關(guān)心得以政。
小紅書的歡迎相關(guān)界面相關(guān)效果很棒,忍不住想模仿著做一下伴找。
注:文章中提到小紅書的開(kāi)發(fā)者將相關(guān)代碼分享到github上了盈蛮,但在下能力欠佳,沒(méi)有搜索到技矮,因此我所有的代碼都是根據(jù)自己的猜測(cè)寫出來(lái)的抖誉,可能有些地方與原作者的實(shí)現(xiàn)方式有所不同甚至缺漏,還請(qǐng)了解的朋友不吝賜教衰倦,另外能Po下他們的git倉(cāng)庫(kù)就更好了??袒炉。
注2:這個(gè)歡迎界面是安卓版的,我不了解iOS的小紅書是不是也是這樣的樊零,懶人如我連下個(gè)App都要命ORZ我磁。
注3:Demo在此
那么,首先來(lái)剖析一下界面相關(guān)效果吧驻襟,首先:
1夺艰、界面由一個(gè)屏幕大小的View(稱為loginView)及一個(gè)略小的View(稱為explainView)組成,它們兩者的職責(zé)分別是展示登錄注冊(cè)相關(guān)界面的跟展示說(shuō)明界面沉衣,并且郁副,兩者都存在動(dòng)畫。
2厢蒜、loginView的動(dòng)畫為:當(dāng)explainView消失時(shí)縮小背景圖霞势、上移登錄注冊(cè)相關(guān)界面。
3斑鸦、explainView動(dòng)畫為:當(dāng)存在于explainView中的ScrollView(稱為explainScrollView)滑動(dòng)到最后時(shí)若用戶繼續(xù)左滑則滑動(dòng)整個(gè)explainView
4愕贡、explainView中有兩個(gè)View承擔(dān)不同職責(zé),explainScrollView及bottomView, explainScrollView展示幀動(dòng)畫(幀動(dòng)畫是我猜的巷屿,另外有一點(diǎn)存疑固以,第一次滑動(dòng)時(shí)沒(méi)有分頁(yè)效果,似乎這里的實(shí)現(xiàn)邏輯有所不同,真想看下他們的代碼)及文字說(shuō)明憨琳,bottomView展示自定義的UIPageControl和一個(gè)UIButton诫钓。(相關(guān)代碼為純布局代碼,不多加敘述)
……
首先篙螟,先來(lái)實(shí)現(xiàn)explainView菌湃,相關(guān)布局代碼不多加敘述,大體上的思路就是根據(jù)屏幕大小換算一個(gè)略小的View遍略,然后在View上放置一個(gè)UIScrollView及UIView(你也可以直接把UIPageControl放在explainView上)惧所,然后就是UIScrollView與UIPageControl的聯(lián)動(dòng)邏輯,接著就可以得到下圖:
好吧绪杏,略丑……
接著是平移explainView下愈,我第一個(gè)思路是想用TouchBegin(Move、End)及手勢(shì)實(shí)現(xiàn)蕾久,但真正操作起來(lái)才發(fā)現(xiàn)這樣代碼繁多势似,并且,完全達(dá)不到想要的效果僧著,思索片刻后找到了另一個(gè)辦法:
//在explainView的外層再套上一個(gè)ScrollView就可以實(shí)現(xiàn)與gif一模一樣的效果酥筝,完全不需要根據(jù)手指挪動(dòng)的Point來(lái)反復(fù)計(jì)算屋群。
let scrollview = UIScrollView(frame: view.frame)
view.addSubview(scrollview)
scrollview.pagingEnabled = true
scrollview.showsVerticalScrollIndicator = false
scrollview.showsHorizontalScrollIndicator = false
scrollview.contentSize = CGSize(width: view.frame.width * 2, height: view.frame.height)
scrollview.delegate = self
//contentView即explainView
let contentView = EPBaseView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width * 2 / 3, height: self.view.frame.height * 2 / 3))
contentView.center = view.center
scrollview.addSubview(contentView)
然后關(guān)聯(lián)explainView與loginView
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
let num = Int(scrollView.contentOffset.x / scrollView.frame.width)
if num > 0 {
//當(dāng)explainView消失時(shí)抹除相關(guān)View并且執(zhí)行l(wèi)oginView相關(guān)動(dòng)畫蜂绎,Demo因?yàn)橥祽兴匀渴鞘褂胒rame的死代碼轮听。
scrollView.removeFromSuperview()
loginView?.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height / 3)
loginView?.updateUI()
}
}
仔細(xì)觀察gif中的loginView相關(guān)動(dòng)畫,你可以發(fā)覺(jué)背景圖與Logo的相關(guān)效果并不一致杯拐,若背景與Logo存在于同一張圖片上會(huì)讓整張圖片壓扁霞篡,不管是花紋還是logo都會(huì)變成一坨爛泥。
所以實(shí)際上應(yīng)該將背景圖與Logo切分開(kāi)來(lái)端逼,比如這樣:
(手頭就一張看著靠譜點(diǎn)的載入圖朗兵,好死好活用PS分離開(kāi)來(lái),沒(méi)有花紋還請(qǐng)多加包涵)
這樣顶滩,我們可以大致推測(cè)出實(shí)現(xiàn)代碼余掖,首先,平鋪背景圖的礁鲁,直接裁剪掉大于View的圖片部分盐欺,當(dāng)執(zhí)行縮小動(dòng)畫時(shí)就能保證花紋不被壓縮。接著是Logo仅醇,獨(dú)立存在的LogoView只要在執(zhí)行動(dòng)畫時(shí)根據(jù)比例縮小并且位移即可冗美。
//當(dāng)說(shuō)明界面消失時(shí)修改登錄界面布局
func updateUI() {
UIView.animateWithDuration(0.3) {
self.backgroundImageView?.frame = self.frame
self.logoImgaeView?.frame = CGRect(x: 0, y: 0, width: 70, height: 70)
self.logoImgaeView?.center = self.center
}
}
接下來(lái)是登錄注冊(cè)界面上移,觀察gif我們可以發(fā)現(xiàn)登錄注冊(cè)兩個(gè)按鈕的背景與背景圖一樣析二,即當(dāng)?shù)卿涀?cè)界面上移時(shí)并不是貼合背景圖而是向上挪動(dòng)了一段距離讓兩個(gè)按鈕鑲嵌在背景圖上粉洼。
//當(dāng)說(shuō)明界面消失時(shí)修改登錄界面布局
func updateUI() {
UIView.animateWithDuration(0.3) {
self.backgroundImageView?.frame = self.frame
self.logoImgaeView?.frame = CGRect(x: 0, y: 0, width: 70, height: 70)
self.logoImgaeView?.center = self.center
//向上多挪動(dòng)60個(gè)點(diǎn)
self.loginView?.frame.origin = CGPoint(x: 0, y: self.frame.height - 60)
}
}
接下來(lái)設(shè)置按鈕的選中圖片以及與登錄注冊(cè)相關(guān)界面(按鈕與ScrollView聯(lián)動(dòng))的相關(guān)邏輯不多加敘述(其實(shí)是我懶)节预。