1. 程式人生 > >Android開源庫SlideMenu如何實現沉浸式效果

Android開源庫SlideMenu如何實現沉浸式效果

作者:zf19921020
轉載請註明出處

SlideMenu是一個在Android上被廣泛使用的開源庫,它是一個仿照IOS左滑選單開發的類似效果。
SlideMenu開源庫GuiHub地址如下:
SlideMenu GitHub

在專案中匯入SlideMenu有兩種方式,一種是將SlideMenu作為Library庫,然後在自己的專案中右鍵點選Properties–>android–>在右下方Library選項將開源庫新增進來,點選apply即可;第二種方式是將SlideMenu專案中的lib包直接複製到我們的專案中(這裡存在第三種方式,可以自己打Jar,略過不談),之後如何開始利用SlideMenu新增選單呢?
第一步,我們一般可以寫個自定義控制元件繼承SlideMenu,其主要程式碼如下:

    private final Activity activity;
    SlidingMenu localSlidingMenu;

    public MySlideMenu(Activity activity) {
        this.activity = activity;
    }

    public SlidingMenu initSlidingMenu() {
        localSlidingMenu = new SlidingMenu(activity);
        localSlidingMenu.setMode(SlidingMenu.LEFT);//設定左右滑選單
localSlidingMenu.setTouchModeAbove(SlidingMenu.SLIDING_WINDOW);//設定要使選單滑動,觸碰螢幕的範圍 //localSlidingMenu.setTouchModeBehind(SlidingMenu.SLIDING_CONTENT); localSlidingMenu.setShadowWidthRes(R.dimen.shadow_width);//設定陰影圖片的寬度 localSlidingMenu.setShadowDrawable(R.drawable.shadow);//設定陰影圖片
localSlidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);//SlidingMenu劃出時主頁面顯示的剩餘寬度 localSlidingMenu.setFadeDegree(0.35F);//SlidingMenu滑動時的漸變程度 localSlidingMenu.attachToActivity(activity, SlidingMenu.SLIDING_WINDOW);//使SlidingMenu附加在Activity右邊 localSlidingMenu.setMenu(R.layout.left_drawer_fragment);//設定menu的佈局檔案 localSlidingMenu.setOnOpenedListener(new SlidingMenu.OnOpenedListener() { public void onOpened() { } }); localSlidingMenu.setOnClosedListener(new OnClosedListener() { @Override public void onClosed() { // TODO Auto-generated method stub } }); return localSlidingMenu; }

其中選單的佈局檔案大家可以自己設定,之後在我們的Activity的OnCreate中新增如下程式碼:

    MySlideMenu slide=new MySlideMenu(this);
    slide.initSlidingMenu();

這樣左滑選單即可成功匯入,效果如下(來自仿今日頭條原始碼):

這裡寫圖片描述

那麼,實現沉浸式選單欄該怎麼做呢:
在Activity設定了佈局檔案之後加入如下程式碼:

if (Environment.getInstance().getOSVersionCode() >= VERSION_CODES.KITKAT) {
            getWindow().addFlags(   WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(           WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            }

因為沉浸式狀態列是在Android4.4才被Google引用的,所以需要先判斷SDK的版本是否超過了KITKAT。在佈局檔案的程式碼中加入如下兩句:

 android:clipToPadding="true"
 android:fitsSystemWindows="true"

這裡是使得控制元件佈局頂到狀態列去。
那麼在SlideMenu中加入沉浸式會是什麼效果呢?請看下圖:
這裡寫圖片描述
圖中顯示,控制元件無法實現沉浸式效果。可真的是如此麼?仔細觀察可以發現,狀態列的顏色確實是改變了,而且變成了白色,那麼說明狀態列是沉浸了的,只是下面的控制元件無法“頂”上去而已,那麼該如何解決呢?
通過扒SlideMenu的原始碼可知,SlideMenu是利用ViewGroup來作為ViewAbove和ViewBehind的容器,而這裡的ViewAbove和ViewBehind就是分別代表我們的主介面佈局檔案和選單佈局檔案。而通過查閱資料我們發現,沉浸式狀態列是僅僅支援Layout和TextView等幾種控制元件的沉浸效果的,而且如果Layout裡面的第一個控制元件為ImageView,沉浸效果也是無法實現的,所以,筆者這裡提供兩個解決方案:
方案一:修改SlideMenu原始碼
在ViewGroup中加入TextView或者其他控制元件作為頂部控制元件來實現,這裡筆者並沒有做過類似工作,所以可行性不敢保證,重點介紹第二種方案;
方案二:曲線救國
分析SlideMenu可知,SlideMenu本身是繼承了RelativeLayout的,所以理所當然的它也可以在佈局檔案中作為view而存在,而這種自定義view是無法直接實現沉浸式效果的,那麼,曲線救國的方式就來了,我們利用一個RelativeLayout包裹住該SlideMenu,然後在該View之前加入一個高度為1dp的TextView,這裡只需把該TextView的Visibity設定為Gone即可不對應用產生任何影響。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/id_main_ly"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:clipToPadding="true"
            android:fitsSystemWindows="true"
            android:visibility="gone" />

        <com.zf.control.slidingmenu.lib.SlidingMenu
            xmlns:sliding="http://schemas.android.com/apk/res-auto"
            android:id="@+id/slidingmenulayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            sliding:behindOffset="0dp"
            sliding:behindScrollScale="1"
            sliding:fadeDegree="0.7"
            sliding:fadeEnabled="true"
            sliding:touchModeAbove="margin"
            sliding:viewAbove="@layout/activity_base" />
    </LinearLayout>

</RelativeLayout>

這裡實現的效果是將整個View直接頂到了狀態列,很明顯這不是我們需要的效果,那麼我們可以得到狀態列的高度,之後設定title_bar的高度和PaddingTop屬性即可解決,程式碼如下:

if (Environment.getInstance().getOSVersionCode() >= VERSION_CODES.KITKAT) {
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().addFlags(
                    WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

            // 改變titlebar的高度
            int statusbarHeight = UIUtils.getStatusBarHeight(getWindow());
            RelativeLayout top_heads = (RelativeLayout) mLeftMenu.getContent()
                    .findViewById(R.id.top_head);
            int height = UIUtils.getMeasureHeightOnCreate(top_heads);
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                    LayoutParams.MATCH_PARENT, height + statusbarHeight);
            top_heads.setLayoutParams(lp);
            top_heads.setPadding(0, statusbarHeight, 0, 0);
            mLeftMenu
                    .getMenu()
                    .findViewById(R.id.logout_layout)
                    .setPadding(0, UIUtils.getStatusBarHeight(getWindow()), 0,
                            0);
        }

最終實現的效果如下:
這裡寫圖片描述