前人種樹
一直想知道 iOS 端的印象筆記(當(dāng)然是老版本了,最新的印象筆記已經(jīng)放棄了這個坑人的動畫)是如何實現(xiàn)的梨睁,在網(wǎng)上搜到了這篇印象筆記交互效果(swift)岭佳,UI 和效果做得都非常好锋华。于是乎怎么也得學(xué)習(xí)學(xué)習(xí)吧披诗,用 OC copy 一份吧迫吐。于是乎開始了踩坑之路。
首先琐鲁,allsome(swift 印象筆記作者)這個 Demo,實現(xiàn)思路是首頁使用 UICollectionView 實現(xiàn)人灼,滑動時候?qū)崟r改變 cell 的 frame 實現(xiàn)類似彈簧的效果围段。但是, 其實這個 Demo有很多的 bug 沒有處理投放,但是仍然是一個很好的思路奈泪,要不是這個 Demo,估計自己怎么也寫不出這個動畫灸芳。
然后涝桅,這個 Demo 的 bug 其實并不是那么容易處理的,我特意抓取了印象筆記 7.18 版本的舊包烙样,發(fā)現(xiàn)印象筆記原版也存在這個 bug冯遂,說不定這就是他們改版的原因呢,哈哈谒获。
下面具體看下這個 bug蛤肌,
造成這個 bug 的主要原因還是用了手勢,在自定義專場中使用了轉(zhuǎn)場手勢批狱,根據(jù)手勢偏移比例可以控制轉(zhuǎn)場的進(jìn)度裸准。
熟悉轉(zhuǎn)場動畫的人應(yīng)該知道,手勢驅(qū)動有一個 bug:假如你設(shè)定赔硫,拖拽比例超過0.5狼速,才決定完成動畫,否則取消動畫。那么當(dāng)你拖拽比例是0.3的時候向胡,那轉(zhuǎn)場動畫就進(jìn)行0.3的比例恼蓬,這個時候松手,轉(zhuǎn)場動畫會重新回到0僵芹,但是屏幕會閃一下处硬。也就是轉(zhuǎn)場從0.3直接回到了0,沒有任何過渡拇派,所以視覺上會閃一下荷辕。
等等,這個 bug 并不是每個轉(zhuǎn)場動畫都會有的件豌,要看你怎么轉(zhuǎn)了疮方,這句話怎么講?我在學(xué)習(xí)轉(zhuǎn)場動畫的時候看了喵神的博客里iOS7中的 VC 切換茧彤,里面的 demo 并不會因為拖拽比例不足返回時發(fā)生卡頓骡显,效果如下
因為這個 Demo,在 dismiss 控制器的時候只是簡單的讓控制器 y 的值從上往下偏移了一個屏幕的距離曾掂,沒有任何寬度和高度的改變惫谤,不會觸發(fā)這個 bug。我把這個 Demo 簡單的改了一下珠洗,dismiss 的時候會同時改變控制器的寬和高溜歪,然后這個惡心的 bug 就會出現(xiàn)了
后人完善
我在wazrx的這篇文章中找到了解決方案,那就是在手勢拖拽比例達(dá)不到我們指定的比例時许蓖,開啟一個CADisplayLink定時器不斷更新轉(zhuǎn)場的進(jìn)度蝴猪,比較好的解決了動畫生硬這個問題。
解決這個主要的 bug 之后膊爪,自己再把一些細(xì)枝末節(jié)完善了一下自阱,就寫成了現(xiàn)在這個 印象筆記 OC
總結(jié)
簡單說一下完成印象筆記的這個Demo需要哪些知識點吧, 其實就兩個:
- 彈簧效果(嚴(yán)格說這個 demo 實現(xiàn)的并不是彈框效果蚁飒,沒有使用到UIDynamic的性質(zhì))
- 自定義轉(zhuǎn)場
在寫這個 Demo 之前特意看了喵神的彈簧效果筆記动壤。但是看到 swift 版本的 Demo 的時候發(fā)現(xiàn)原作者并沒有使用這個效果,而是在 collectionView 滑動的時候動態(tài)計算了每個 cell 的 frame淮逻,改變了每個 cell 的 y 值琼懊,從而實現(xiàn)了這個效果,不得不說非常棒爬早!因為如果使用了 UIDynamic 實現(xiàn)彈簧效果哼丈,在點擊 cell 進(jìn)入轉(zhuǎn)場動畫的時候會非常混亂筛严。所以原作者這個方法簡單醉旦,實用!
轉(zhuǎn)場動畫具體介紹網(wǎng)上實在太多了,可以自行百度车胡,google檬输。主要思想其實是: 以前怎么 modal 一個控制器是系統(tǒng)自己決定的,怎么 dismiss 也是系統(tǒng)決定的匈棘。 iOS7之后丧慈,Apple 提供了一套 API 給我們,我們可以自己決定如何 dismiss主卫,如何 modal逃默。
在allsome的 swift 版本的 demo 中,所有轉(zhuǎn)場代理都在一個文件里簇搅,我為了讓結(jié)構(gòu)更加清晰完域,把轉(zhuǎn)場代理全部分開,一共三個文件瘩将。
- 告訴我你想如何 present 一個控制器吟税。
- 告訴我你想如何 dissmiss 掉一個控制器。
- 告訴我你手勢驅(qū)動比例和dismiss 控制器的關(guān)系鸟蟹。
最后的一點討論
這個 Demo 中乌妙,點擊 collectionView 的 cell使兔,present出 MYNoteVC建钥。
然后在使用手勢 dismiss 的時候,只要手勢開始 MYNoteVC 的 view 就被我們隱藏了虐沥,動畫效果全部在 collectionView 上完成熊经,所以手勢沒有完成的時候開啟定時器,我們其實是對collectionView 做動畫欲险,正因為這個特性镐依,才能使用定時器這個技巧解決動畫生硬的問題。 如果我們直接對 MYNoteVC 做動畫的話天试,定時器這個技巧也不能很好的完成這個動畫槐壳,但是為什么wazrx的這篇文章的 Demo 里都沒有任何不妥呢,原因有兩個
wazrx 的這個 Demo 里 A -> B喜每,B在dismiss 的時候?qū)嶋H上是對 B 的 view 的截圖進(jìn)行動畫务唐,并不是真正的 B 的 View。那印象筆記的 Demo 為什么不能對截圖做動畫呢带兜? 因為還要實時改變控制器 title 和返回圖標(biāo)的 frame 和 alpha枫笛。
印象筆記的 Demo 里 A -> B, B在dismiss的時候是先隱藏 B,實際對 A 進(jìn)行動畫刚照。因為 A 和 B 長得一樣刑巧,所以并看不出來。如果 B在 dismiss 的時候就真的對 B 進(jìn)行動畫,那么手勢取消的時候還是會有bug啊楚。
本文 Demo
allsome的印象筆記 Swift
wazrx轉(zhuǎn)場取消時開啟定時器文章
好像也沒什么可說的吠冤,只有動手寫了,才更明白恭理。