什么?你們不知道簡書app可以側(cè)滑退出桐罕?
還不趕緊掏出手機試一試脉让。
發(fā)現(xiàn)越來越多的app有實現(xiàn)側(cè)滑退出了,這是之前仿寫《最美有物》時候?qū)崿F(xiàn)的功能功炮。給大家分享一下溅潜。
嗯,其實沒有蒙大家薪伏,用封裝好的基類直接繼承就好了滚澜,只要寫兩個單詞,不算欺騙哈嫁怀。心急的同學(xué)可以直接滾到下面拿走代碼直接測試一下设捐。不急的話就來一起看看實現(xiàn)方式吧~
先來看看效果圖
實現(xiàn)思路
當時參考了網(wǎng)絡(luò)上諸多側(cè)滑退出的方法,主要有以下三種方式:
1.監(jiān)聽頁面的手勢滑動配合動畫來實現(xiàn)
2.通過自定義View塘淑,直接在自定義的ViewGroup中完成手勢操作
3.使用帶側(cè)滑的Android SlidePaneLayout控件加工萝招。
而我是用側(cè)滑基類封裝采用的正是第三種,通過帶側(cè)滑功能的SlidingPaneLayout為主體存捺,也是膜拜一下大神的構(gòu)思槐沼,我也是看到了加了點定制需求就用上了。
SlidingPanelLayout可能有的同學(xué)不是很熟悉召噩,用的比較多的還是 DrawerLayout母赵。但是兩者其實很相似,都是一個提供側(cè)邊擴展菜單的布局容器具滴。
簡單講一下 SlidingPanelLayout和DrawerLayout的區(qū)別:
- SlidingPanelLayout只能定義一個左邊的隱藏布局凹嘲,而DrawerLayout左右都可以。
- SlidingPanelLayout的側(cè)邊欄拉出時构韵,主界面也會同時向右滑動周蹭,而DrawerLayout會覆蓋在上面(當然趋艘,DrawerLayout可以自定義各種滑動特效,這個效果完全不在話下)
- SlidingPanelLayout可以在任意位置拉出側(cè)邊凶朗,而DrawerLayout只能在靠近邊緣的位置(這個參數(shù)應(yīng)該也是可以改的瓷胧,原來看到過)
這幾點大概也就是選用SlidingPanelLayout來實現(xiàn)側(cè)滑退出而不用DrawerLayout的原因了。
到這里大家應(yīng)該就明白了大概的原理棚愤,我們主要做的事情有這幾點
- 將我們的頁面作為SlidePaneLayout的主界面展示
- 將側(cè)滑出的菜單欄設(shè)置為透明
- 拉出菜單欄然后finish掉activity
這樣一個簡單的側(cè)滑退出就實現(xiàn)了搓萧。當然要做的不止這些,實現(xiàn)起來還是有不少細節(jié)需要注意的宛畦。
先上完整代碼
public abstract class SwipeBackActivity extends BaseActivity implements SlidingPaneLayout.PanelSlideListener {
@Override
public void init() {
initSwipeBackFinish();
}
public void backClick(View view){
this.finish();
//設(shè)置Activity退出的動畫
this.overridePendingTransition(0, R.anim.slide_finish);
}
@Override
protected boolean isOpenStatus() {
return false;
}
/**
* 是否支持滑動退出
*/
protected boolean isSupportSwipeBack() {
return true;
}
/**
* 側(cè)滑退出activity
*/
public void initSwipeBackFinish() {
if (isSupportSwipeBack()) {
SlidingPaneLayout slidingPaneLayout = new SlidingPaneLayout(this);
//通過反射改變mOverhangSize的值為0瘸洛,這個mOverhangSize值為菜單到右邊屏幕的最短距離,
//默認是32dp
try {
//更改屬性
Field field = SlidingPaneLayout.class.getDeclaredField("mOverhangSize");
field.setAccessible(true);
field.set(slidingPaneLayout, 0);
} catch (Exception e) {
e.printStackTrace();
}
//設(shè)置監(jiān)聽事件
slidingPaneLayout.setPanelSlideListener(this);
slidingPaneLayout.setSliderFadeColor(getResources().getColor(android.R.color.transparent));
View leftView = new View(this);
leftView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//在左邊添加這個視圖
slidingPaneLayout.addView(leftView, 0);
//獲取到最頂層的視圖容器
ViewGroup decor = (ViewGroup) getWindow().getDecorView();
//獲取到右邊的視圖
ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
//設(shè)置左邊的視圖為透明
decorChild.setBackgroundColor(getResources().getColor(android.R.color.transparent));
decor.removeView(decorChild);
decor.addView(slidingPaneLayout);
//在右邊添加這個視圖
slidingPaneLayout.addView(decorChild, 1);
}
}
@Override
public void onPanelSlide(View panel, float slideOffset) {
SlidingPaneLayout slidingPaneLayout = (SlidingPaneLayout) panel.getParent();
slidingPaneLayout.getChildAt(0).setBackgroundColor(Color.BLACK);
slidingPaneLayout.getChildAt(0).setAlpha((float) (1 - slideOffset / 1.1));
if (slideOffset == 1) {
slidingPaneLayout.getChildAt(0).setAlpha(0);
}
//panel.setBackgroundColor(Color.BLACK);
Log.d("print", "onPanelSlide: " + slideOffset);
}
@Override
public void onPanelOpened(View panel) {
finish();
//設(shè)置Activity退出的動畫
this.overridePendingTransition(0, R.anim.slide_finish);
}
@Override
public void onPanelClosed(View panel) {
}
}
主要的代碼就是這個 initSwipeBackFinish()
方法了次和。開頭先通過反射修改一個邊距相關(guān)的值為0反肋,為了讓我們的側(cè)滑能更流暢的一滑到底而不是截然而止.....
設(shè)置監(jiān)聽,這個 PanelSlideListener
有 onPanelSlide
踏施、onPanelOpen
石蔗、onPanelClose
三個方法,比較簡單畅形,我在過程中方法通過偏移量簡單的設(shè)置透明度的變化养距,這樣可以在退出時可以隨滑動距離產(chǎn)生陰影到全透的變化在結(jié)束,這是當時《最美有物》的效果日熬,我大概的模仿了一下铃在。
然后在Open即全部滑出的時候finish掉了Activity,順帶使用一個退出動畫完成過渡碍遍。
核心就是這一大段注釋的位置了
View leftView = new View(this);
leftView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//在左邊添加這個視圖
slidingPaneLayout.addView(leftView, 0);
//獲取到最頂層的視圖容器
ViewGroup decor = (ViewGroup) getWindow().getDecorView();
//獲取到右邊的視圖
ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
//設(shè)置左邊的視圖為透明
decorChild.setBackgroundColor(getResources().getColor(android.R.color.transparent));
decor.removeView(decorChild);
decor.addView(slidingPaneLayout);
//在右邊添加這個視圖
slidingPaneLayout.addView(decorChild, 1);
解釋一下左邊右邊
- new 了一個 左邊視圖定铜,透明的,放在的slidingPanellayout 的child 0的位置怕敬,這個就是我們的側(cè)邊欄啦
- 然后通過 DecorView直接從窗口拿到我們的主activity界面(不用傳layout id 過來自己inflate了)把它放到 slidingPanelLayout的右邊 child 1揣炕,即正常展示位置。
- 把原本窗口的布局移除东跪,替換成我們自己的SlidingPanelLayout畸陡,嗯,一波太子換貍貓虽填,成功把側(cè)滑退出功能附給了我們的Activity丁恭。
這樣就算是大功告成 。
其實代碼還是比較少的斋日,實現(xiàn)起來也相當簡單牲览。
總結(jié)
相對而言,這種簡單的方式避開了新手最不喜歡的手勢操作恶守,事件分發(fā)等技術(shù)點(沒錯第献,就是當年的我)贡必,缺點是可定制程度低,需求變成上滑退出庸毫,下拉退出什么的仔拟,就要一臉懵逼了。不過作為一個簡單實現(xiàn)的方式飒赃,還是值得收藏的利花。