利用DrawerLayout實現自定義左右抽屜佈局——什麼抽屜都是浮雲
本文首發於公眾號“AntDream”,歡迎微信搜尋“AntDream”或掃描文章底部二維碼關注,和我一起每天進步一點點
抽屜佈局的樣式很多應用中都有應用,比如滴滴。其實實現也比較簡單,就是用官方的DrawerLayout和NavigationView。具體的程式碼實現如果不熟悉了的話可以用Android+Studio/">Android Studio新建一個專案,在新增Activity時選擇NavigationDrawerActivity,就可以檢視具體的實現程式碼了。

系統的抽屜實現
這次我們主要講怎麼自定義抽屜的佈局,因為實際開發過程中我們很可能需要開發五花八門的樣式。
其實實現的方式也很簡單,就是用自定義的佈局替換掉NavigationView。
常規的抽屜佈局
我們按照文章開頭的方式新建專案以後就可以看到MainActivity的佈局大概是這樣的:
//最外層是DrawerLayout <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> //這裡是主頁面 <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> //這裡是彈出的抽屜佈局 <android.support.design.widget.NavigationView android:id="@+id/nav_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </android.support.v4.widget.DrawerLayout>
可以看到結構很簡單,就是最外層DrawerLayout,然後裡面包了一個主頁面的佈局和抽屜佈局。
原始的抽屜佈局包括2部分:
- 頭部佈局:對應NavigationView的headerLayout屬性
- 選單:對應NavigationView的menu屬性
自定義抽屜佈局
好的,有些小夥伴可能已經猜到了。沒錯,要想自定義抽屜佈局,我們需要把NavigationView給替換掉。
//最外層是DrawerLayout <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> //這裡是主頁面 <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> //這裡是彈出的抽屜佈局 <LinearLayout android:layout_width="160dp" android:layout_height="match_parent" android:orientation="vertical" android:layout_gravity="start" android:background="#fff" android:fitsSystemWindows="true" android:paddingTop="30dp"> <ListView android:id="@+id/lvListViewRight" android:layout_width="160dp" android:layout_height="match_parent" android:dividerHeight="0dp" android:divider="@null" android:background="@null"/> </LinearLayout> </android.support.v4.widget.DrawerLayout>
其中需要注意的是抽屜的方向,這個由layout_gravity屬性來確定,start表示從左側彈出,設定為end就是右側的抽屜。
當然,這需要在程式碼中DrawerLayout相關方法的配合。
- 獲取DrawerLayout
mDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
- 開啟左側的抽屜
if (!mDrawer.isDrawerOpen(GravityCompat.START)) { mDrawer.openDrawer(GravityCompat.START); }
- 開啟右側的抽屜
if (!mDrawer.isDrawerOpen(GravityCompat.END)) { mDrawer.openDrawer(GravityCompat.END); }
左右雙抽屜
不知道小夥伴們有沒有思路。
(1)思路一:2個抽屜,那我就上2個NavigationView唄!
//最外層是DrawerLayout <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> //這裡是主頁面 <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> //這裡是彈出的抽屜佈局,左側 <android.support.design.widget.NavigationView android:id="@+id/nav_view_left" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> //這裡是彈出的抽屜佈局,右側 <android.support.design.widget.NavigationView android:id="@+id/nav_view_right" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="end" android:fitsSystemWindows="true" app:headerLayout="@layout/nav_header_main" app:menu="@menu/activity_main_drawer" /> </android.support.v4.widget.DrawerLayout>
只需要分別設定layout_gravity為start和end就行了,對應的DrawerLayout程式碼就不貼了。
(2)思路二:上面的靈活性不太夠,滿足不了需求,咋整?那就通通自定義!
//最外層是DrawerLayout <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:openDrawer="start"> //這裡是主頁面 <include layout="@layout/app_bar_main" android:layout_width="match_parent" android:layout_height="match_parent" /> //這裡是彈出的抽屜佈局,左側 <LinearLayout android:layout_width="160dp" android:layout_height="match_parent" android:orientation="vertical" android:layout_gravity="start" android:background="#fff" android:fitsSystemWindows="true" android:paddingTop="30dp"> <ListView android:id="@+id/lvListViewLeft" android:layout_width="160dp" android:layout_height="match_parent" android:dividerHeight="0dp" android:divider="@null" android:background="@null"/> </LinearLayout> //這裡是彈出的抽屜佈局,右側 <LinearLayout android:layout_width="160dp" android:layout_height="match_parent" android:orientation="vertical" android:layout_gravity="end" android:background="#fff" android:fitsSystemWindows="true" android:paddingTop="30dp"> <ListView android:id="@+id/lvListViewRight" android:layout_width="160dp" android:layout_height="match_parent" android:dividerHeight="0dp" android:divider="@null" android:background="@null"/> </LinearLayout> </android.support.v4.widget.DrawerLayout>
同樣的,用LinearLayout的layout_gravity控制左右抽屜。
其他
不知道小夥伴們注意到一個細節沒有,上面的佈局檔案中有一個屬性無論是NavigationView還是自定義佈局都用到了:
android:fitsSystemWindows="true"
這個是幹啥的呢?
呃...你去掉試試看效果就知道了,哈哈!
歡迎關注我的微信公眾號,和我一起每天進步一點點!

AntDream