Material Design - DrawerLayout

關(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)代碼開始

鏈接:官網(wǎng)鏈接,科學(xué)食用

抽屜式導(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)閉事件
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

NavigationViewdesign 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é)食用 口味更佳


---- 以上就是全部內(nèi)容
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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