連一行代碼都不用跨琳!教你快速實現(xiàn)簡書app側(cè)滑退出功能

什么?你們不知道簡書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ū)別:

  1. SlidingPanelLayout只能定義一個左邊的隱藏布局凹嘲,而DrawerLayout左右都可以。
  2. SlidingPanelLayout的側(cè)邊欄拉出時构韵,主界面也會同時向右滑動周蹭,而DrawerLayout會覆蓋在上面(當然趋艘,DrawerLayout可以自定義各種滑動特效,這個效果完全不在話下)
  3. SlidingPanelLayout可以在任意位置拉出側(cè)邊凶朗,而DrawerLayout只能在靠近邊緣的位置(這個參數(shù)應(yīng)該也是可以改的瓷胧,原來看到過)

這幾點大概也就是選用SlidingPanelLayout來實現(xiàn)側(cè)滑退出而不用DrawerLayout的原因了。

到這里大家應(yīng)該就明白了大概的原理棚愤,我們主要做的事情有這幾點

  1. 將我們的頁面作為SlidePaneLayout的主界面展示
  2. 將側(cè)滑出的菜單欄設(shè)置為透明
  3. 拉出菜單欄然后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)聽,這個 PanelSlideListeneronPanelSlide 踏施、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);

解釋一下左邊右邊

  1. new 了一個 左邊視圖定铜,透明的,放在的slidingPanellayout 的child 0的位置怕敬,這個就是我們的側(cè)邊欄啦
  2. 然后通過 DecorView直接從窗口拿到我們的主activity界面(不用傳layout id 過來自己inflate了)把它放到 slidingPanelLayout的右邊 child 1揣炕,即正常展示位置。
  3. 把原本窗口的布局移除东跪,替換成我們自己的SlidingPanelLayout畸陡,嗯,一波太子換貍貓虽填,成功把側(cè)滑退出功能附給了我們的Activity丁恭。
    這樣就算是大功告成 。

其實代碼還是比較少的斋日,實現(xiàn)起來也相當簡單牲览。

總結(jié)

相對而言,這種簡單的方式避開了新手最不喜歡的手勢操作恶守,事件分發(fā)等技術(shù)點(沒錯第献,就是當年的我)贡必,缺點是可定制程度低,需求變成上滑退出庸毫,下拉退出什么的仔拟,就要一臉懵逼了。不過作為一個簡單實現(xiàn)的方式飒赃,還是值得收藏的利花。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市载佳,隨后出現(xiàn)的幾起案子晋被,更是在濱河造成了極大的恐慌,老刑警劉巖刚盈,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異挂脑,居然都是意外死亡藕漱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門崭闲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肋联,“玉大人,你說我怎么就攤上這事刁俭¢先裕” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵牍戚,是天一觀的道長侮繁。 經(jīng)常有香客問我,道長如孝,這世上最難降的妖魔是什么宪哩? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮第晰,結(jié)果婚禮上锁孟,老公的妹妹穿的比我還像新娘。我一直安慰自己茁瘦,他們只是感情好品抽,可當我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著甜熔,像睡著了一般圆恤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上腔稀,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天哑了,我揣著相機與錄音赘方,去河邊找鬼。 笑死弱左,一個胖子當著我的面吹牛窄陡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拆火,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼跳夭,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了们镜?” 一聲冷哼從身側(cè)響起币叹,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎模狭,沒想到半個月后颈抚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡嚼鹉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年贩汉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锚赤。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡匹舞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出线脚,到底是詐尸還是另有隱情赐稽,我是刑警寧澤,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布浑侥,位于F島的核電站姊舵,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏寓落。R本人自食惡果不足惜蠢莺,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望零如。 院中可真熱鬧躏将,春花似錦、人聲如沸考蕾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肖卧。三九已至蚯窥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拦赠。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工巍沙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荷鼠。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓句携,卻偏偏與公主長得像,于是被迫代替她去往敵國和親允乐。 傳聞我的和親對象是個殘疾皇子矮嫉,可洞房花燭夜當晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容