關(guān)鍵字:DrawerLayout、材料設(shè)計
項目地址:AboutMaterialDesign
注意:代碼基于 android.support.design 26.0.0
在材料設(shè)計出現(xiàn)之前,想要實現(xiàn)下面的布局,必須自定義實現(xiàn),多虧了開源社區(qū),那時候我們可以用 SlidingMenu 等優(yōu)秀的第三方模塊來實現(xiàn)相關(guān)功能。今天我們要介紹 google 推出的抽屜布局
一、從搬運官網(wǎng)代碼開始
抽屜式導(dǎo)航欄是一個面板,它將應(yīng)用的主要導(dǎo)航選項顯示在屏幕邊緣。大多數(shù)情況下,它處于隱藏狀態(tài),但是如果用戶從屏幕左邊緣滑動手指,它就會顯示出來。
抽屜式導(dǎo)航欄設(shè)計
決定在應(yīng)用中使用抽屜式導(dǎo)航欄之前, 應(yīng)該了解抽屜式導(dǎo)航欄設(shè)計 指南中定義的用例和設(shè)計原則。材料設(shè)計的原則如果想詳細了解,還可以戳這里
1)創(chuàng)建簡單抽屜布局
現(xiàn)在來創(chuàng)建一個簡單的抽屜布局,要添加抽屜式導(dǎo)航欄,需要將包含 DrawerLayout 對象的用戶界面聲明為布局的根視圖。在 DrawerLayout 內(nèi),添加一個包含屏幕主內(nèi)容(當抽屜式導(dǎo)航欄處于隱藏狀態(tài)時為主要布局)的視圖和另一個包含抽屜式導(dǎo)航欄內(nèi)容的視圖。
<!--例如,以下布局使用包含兩個子視圖的 DrawerLayout:-->
<!--包含主內(nèi)容的 FrameLayout(在運行時由 Fragment 填充)-->
<!--和抽屜式導(dǎo)航欄的 ListView-->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
- 此布局演示了一些重要的布局特性:
- 1.主內(nèi)容視圖(上面的 FrameLayout)必須是第一個子視圖,因為 XML 順序意味著按 z 序(層疊順序)排序,并且抽屜式導(dǎo)航欄必須位于內(nèi)容頂部。主內(nèi)容視圖設(shè)置為匹配父視圖的寬度和高度, 因為在抽屜式導(dǎo)航欄處于隱藏狀態(tài)時, 它代表整個 UI。
- 2.抽屜式導(dǎo)航欄視圖 (ListView) 必須使用 android:layout_gravity 屬性指定其水平重力。要支持“從右到左”(RTL) 語言,請使用 "start"(而非 "left")指定該值(這樣當布局為 RTL 時,抽屜式導(dǎo)航欄會顯示在右側(cè))。
- 3.抽屜式導(dǎo)航欄視圖以 dp 為單位指定其寬度, 且高度與父視圖相匹配。抽屜式導(dǎo)航欄的寬度不應(yīng)超過 320dp,從而用戶始終可以看到部分主內(nèi)容。
2)初始化抽屜式導(dǎo)航欄列表
直接貼代碼了,listview 的數(shù)據(jù)填充應(yīng)該都沒有大的問題
public class MainActivity extends Activity {
private String[] mPlanetTitles;
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set the adapter for the list view
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
// Set the list's click listener
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
...
}
}
3)監(jiān)聽打開和關(guān)閉事件
-
DrawerLayout.DrawerListener
監(jiān)聽的方法名也很人性,一看就懂
Type | Interface Discription |
---|---|
abstract void | onDrawerClosed(View drawerView) |
abstract void | onDrawerOpened(View drawerView) |
abstract void | onDrawerSlide(View drawerView,float slideOffset) |
abstract void | onDrawerStateChanged(int newState) |
onDrawerStateChanged 的對應(yīng)值
Type | Name | Constant Discription |
---|---|---|
int | STATE_DRAGGING | Indicates that a drawer is currently being dragged by the user. |
int | STATE_IDLE | Indicates that any drawers are in an idle, settled state. No animation is in progress. |
int | STATE_SETTLING | Indicates that a drawer is in the process of settling to a final position. |
---- 以上就是官網(wǎng)文檔的全部內(nèi)容,當然還有一點點關(guān)于 ActionBarDrawerToggle 的介紹,有興趣可以自行了解。
二、簡單的使用
其實最簡單的使用官網(wǎng)已經(jīng)列出了,按照上面的代碼就可以寫出一個最簡單的抽屜布局。
三、更進一步,NavigationView
NavigationView 是 design 22.2.0 加入的一個新的類,如果支持包版本過低,是沒有的。它的出現(xiàn)彌補了上面簡單布局中實現(xiàn) ListView 布局的繁瑣,可以讓我們快速實現(xiàn)抽屜欄的布局。(就像文章開頭的效果一樣)
貼上倉庫的部分代碼,如果全部代碼,可以到倉庫鏈接克隆。
鏈接:倉庫傳送門
<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/activity_drawer_drawerlayoutId"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimary"
tools:context="com.arno.aboutmaterialdesign.drawerlayout.DrawerLayoutActivity">
<!--主布局-->
<include layout="@layout/content_drawerlayout_drawer"/>
<!--抽屜布局-->
<!--Attention:-->
<!--android:layout_gravity="start" 屬性一定要設(shè)置,這是作為抽屜的標志-->
<!--這里的代碼很可能沒有聯(lián)想,需要手動輸入-->
<android.support.design.widget.NavigationView
android:id="@+id/activity_drawer_nav"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/header_drawerlayout"
app:menu="@menu/menu_drawer"
android:background="@color/colorPrimaryDark"
></android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
使用 NavigationView 會有這樣的問題:
- 1.item 設(shè)置的圖片沒有色彩
- 2.取消滾動條的有效方法找不到
- 3.item 文字樣式怎么設(shè)置
//去除滾動條
mNavigationView.getChildAt(0).setVerticalScrollBarEnabled(false);
//設(shè)置圖片有色彩
mNavigationView.setItemIconTintList(null);
//設(shè)置文字顏色
mNavigationView.setItemTextColor(getResources().getColorStateList(R.color.selector_nav_menu_item));
//設(shè)置文字其他樣式
mNavigationView.setItemTextAppearance(R.style.main_nav_menu_item_text_appearance);
NavigationView 有一個內(nèi)部的監(jiān)聽方法:
NavigationView.OnNavigationItemSelectedListener
另,menu 和 header 除了像上面那樣在 xml 中設(shè)置,也可以在代碼里設(shè)置:
//Header 相關(guān)
addHeaderView(View v)
inflateHeaderView(int res)
getHeaderCount()
getHeaderView(int index)
removeHeaderView(View v)
//Menu 相關(guān)
getMenu()
inflateMenu()
也許你會覺得,好像哪里還有點不如意,不如看看 Menu 這個文件的屬性,是不是能幫到你
鏈接:Menu 科學(xué)食用 口味更佳