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);
}
最終實現的效果如下: