iOS應(yīng)用有一個(gè)普遍的功能——滑動(dòng)返回,手指從左邊緣向右滑動(dòng)汰规,手指松開時(shí)到達(dá)一定條件汤功,返回上層界面。在Android系統(tǒng)中溜哮,微信和簡(jiǎn)書也實(shí)現(xiàn)了這樣的功能滔金。網(wǎng)上有一些開源庫色解,也實(shí)現(xiàn)了滑動(dòng)返回部宿,用的時(shí)候不很滿足需求惊科,像沒有背景聯(lián)動(dòng);而且由于需要繼承滑動(dòng)返回基類算灸,破壞原項(xiàng)目的繼承關(guān)系忿族。
先來看看微信的效果:
下面是我實(shí)現(xiàn)的锣笨,有木有感覺效果都達(dá)到了O(∩_∩)O~~,這是在項(xiàng)目中的應(yīng)用效果
源碼地址:https://github.com/jinxiyang/SwipeBackLibrary
滑動(dòng)返回原理
滑動(dòng)返回的實(shí)現(xiàn)方式肠阱,并不我想出來的票唆,我只是站在了巨人的肩膀上,優(yōu)化他人的實(shí)現(xiàn)方式屹徘,再添加上自己的理解才寫出了這個(gè)項(xiàng)目走趋。文末列出參考的博客和代碼,在此表示由衷的感謝噪伊。
如上圖所示簿煌,APP應(yīng)用的界面是一層一層的,A在最底層鉴吹,A上面有B姨伟,B上面有C,……豆励,D在最頂層夺荒。滑動(dòng)返回原理,其實(shí)就是監(jiān)聽手指在屏幕上的滑動(dòng)手勢(shì)良蒸,移動(dòng)頂層界面和下一層界面技扼。當(dāng)手指從屏幕左邊緣開始向右滑動(dòng)時(shí),使頂層界面(例如D)透明嫩痰;隨著手指向右滑動(dòng)剿吻,向右移動(dòng)頂層界面D,則左邊就會(huì)空出來串纺,進(jìn)而看到下一層的界面丽旅;當(dāng)松開手指時(shí),移動(dòng)的距離超過一定的閾值纺棺,觸發(fā)頂層界面D的銷毀榄笙,C界面的顯示出來。
怎么樣祷蝌,原理是不是很簡(jiǎn)單办斑。下圖是滑動(dòng)返回的示意圖:
難點(diǎn)
是的,原理很簡(jiǎn)單,但實(shí)現(xiàn)起來卻有幾個(gè)難點(diǎn)乡翅。理想很美好,現(xiàn)實(shí)很殘酷罪郊。
對(duì)于界面蠕蚜,可能是Activity(這里指DecorView),也可能是Fragment(這里指fragment.getView())悔橄,那頂層和下層界面就有好幾種情況了靶累。
怎么樣監(jiān)聽手勢(shì)滑動(dòng),會(huì)不會(huì)和界面中的滑動(dòng)控件產(chǎn)生沖突癣疟。
怎樣實(shí)現(xiàn)頂層界面透明挣柬,在滑動(dòng)時(shí)顯示下層界面,以及下層界面的聯(lián)動(dòng)睛挚。
當(dāng)項(xiàng)目中已經(jīng)有一套自己定義的轉(zhuǎn)場(chǎng)動(dòng)畫邪蛔,當(dāng)滑動(dòng)到一定的閾值銷毀頂層界面時(shí),如何處理轉(zhuǎn)場(chǎng)動(dòng)畫扎狱。
如何以最小的侵入性嵌入已有的項(xiàng)目侧到,而不改變?cè)械睦^承關(guān)系,而不大改動(dòng)原有代碼淤击。
滑動(dòng)返回的Android版本兼容性匠抗。
好在是站在巨人的肩膀上,這些前人已經(jīng)都有解決方案污抬,我們不必重復(fù)造輪子汞贸,我們只需要整理并優(yōu)化,寫出一套符合需求的代碼印机。話說難點(diǎn)這么多矢腻,有什么方案可以解決呢?且聽我娓娓道來耳贬。
1踏堡、 難點(diǎn)一:
對(duì)于界面,可能是Activity(這里指DecorView)咒劲,也可能是Fragment(這里指fragment.getView())顷蟆,那頂層和下層界面就有好幾種情況了。
分析:仔細(xì)想一下腐魂,也就兩種情況:
- 當(dāng)上下兩層界面都在同一activity內(nèi)時(shí)帐偎,頂層是Fragment,下層也是Fragment蛔屹。
- 當(dāng)上下兩層界面不在同一activity內(nèi)時(shí)削樊,頂層應(yīng)該最多有一個(gè)Fragment,那頂層界面是activity,下層界面是activity漫贞。
因此可知滑動(dòng)返回甸箱,就是發(fā)生在Fragment和Fragment之間、activity和activity之間迅脐。
2芍殖、 難點(diǎn)二:
怎么樣監(jiān)聽手勢(shì)滑動(dòng),會(huì)不會(huì)和界面中的滑動(dòng)控件產(chǎn)生沖突谴蔑。
分析:Android提供了ViewDragHelper這個(gè)類豌骏,專門用來處理手勢(shì)拖動(dòng)事件的,廣泛的應(yīng)用于自定義ViewGroup的過程中隐锭,像Navigation Drawer的邊緣滑動(dòng)等窃躲。在這里我們用它來監(jiān)聽用戶的手勢(shì)拖動(dòng),捕獲指定的View钦睡,設(shè)置頂層界面的位置蒂窒,移動(dòng)背景界面的位置,實(shí)現(xiàn)頂層界面隨著手指而移動(dòng)赎婚,背景界面聯(lián)動(dòng)刘绣。后面源碼分析,具體介紹該類如何使用挣输。
3纬凤、 難點(diǎn)三:
怎樣實(shí)現(xiàn)頂層界面透明,在滑動(dòng)時(shí)顯示下層界面撩嚼,以及下層界面的聯(lián)動(dòng)停士。
分析:
- fragment之間,移動(dòng)頂層fragment完丽,下層fragment設(shè)置setVisibility(VISIBLE)恋技,即可看到下層fragment,然后FragmentManager獲取下層framgent逻族,移動(dòng)其位置即可背景聯(lián)動(dòng)蜻底。 無版本兼容問題。
- activity之間聘鳞,將頂層activity轉(zhuǎn)為透明薄辅,移動(dòng)activity的DecorView時(shí),即可看到下層的activity抠璃。將頂層activity轉(zhuǎn)為透明站楚,需要反射調(diào)用activity的convertToTranslucent方法。在Android 4.x部分手機(jī)上有問題搏嗡,5.0及其以后窿春,無問題拉一。
4、 難點(diǎn)四:
當(dāng)項(xiàng)目中已經(jīng)有一套自己定義的轉(zhuǎn)場(chǎng)動(dòng)畫旧乞,當(dāng)滑動(dòng)到一定的閾值銷毀頂層界面時(shí)蔚润,如何處理轉(zhuǎn)場(chǎng)動(dòng)畫。
分析:
activity的轉(zhuǎn)場(chǎng)動(dòng)畫良蛮,只需在startActivity抽碌、finish后使用overridePendingTransition()即可。
-
fragment的轉(zhuǎn)場(chǎng)動(dòng)畫决瞳,在setCustomAnimations方法中設(shè)置
getSupportFragmentManager() .beginTransaction() .setCustomAnimations(R.anim.activity_or_fragment_enter, R.anim.activity_or_fragment_exit, R.anim.activity_or_fragment_pop_enter, R.anim.activity_or_fragment_pop_exit) .add(R.id.contentFrame, nextFragment, nextFragment.getClass().getSimpleName()) .hide(currFragment) .addToBackStack(currFragment.getClass().getSimpleName()) .commit();
在這里設(shè)置好了之后,fragment界面正常退出時(shí)左权,會(huì)調(diào)用設(shè)置的退出動(dòng)畫皮胡。但是當(dāng)手指從左到右滑動(dòng),松開時(shí)超過一定的閾值時(shí)赏迟,觸發(fā)頂層界面的銷毀屡贺,這時(shí)頂層界面需要無動(dòng)畫退出。
Fragment有個(gè)方法onCreateAnimation锌杀,當(dāng)轉(zhuǎn)場(chǎng)動(dòng)畫發(fā)生前甩栈,會(huì)回調(diào)此方法。我們重寫此方法糕再,在觸發(fā)頂層界面的銷毀前量没,鎖住動(dòng)畫即isLocking()返回true,該方法onCreateAnimation返回?zé)o動(dòng)畫突想。
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if (isLocking()) {
return mNoAnim;
}
return super.onCreateAnimation(transit, enter, nextAnim);
}
5殴蹄、 難點(diǎn)五:
如何以最小的侵入性嵌入已有的項(xiàng)目,而不改變?cè)械睦^承關(guān)系猾担,而不大改動(dòng)原有代碼袭灯。
分析:為fagment、activity定義相應(yīng)的接口绑嘹,在提供一個(gè)實(shí)現(xiàn)類稽荧,面向接口編寫,嵌入你的項(xiàng)目時(shí)工腋,讓你項(xiàng)目的基類實(shí)現(xiàn)姨丈。即可少改動(dòng)你的項(xiàng)目代碼,不用改動(dòng)庫的代碼夷蚊。
6构挤、 難點(diǎn)六:
滑動(dòng)返回的Android版本兼容性。
分析:版本兼容問題在難點(diǎn)三中已經(jīng)體現(xiàn)惕鼓。如果你的項(xiàng)目使用“單activity多fragment”架構(gòu)筋现,無版本兼容問題。若使用“多activity多fragment”架構(gòu),4.x系統(tǒng)部分手機(jī)有問題矾飞,5.0及其以后無問題一膨。
致謝
滑動(dòng)返回庫:
https://github.com/ikew0ng/SwipeBackLayout
https://github.com/YoKeyword/SwipeBackFragment.git
https://github.com/tyzlmjj/SwipeBack
Android ViewDragHelper源碼解析
http://www.cnblogs.com/lqstayreal/p/4500219.html