Drawer 詳解 ·Material Design Part 3

ccheima 8年前發布 | 10K 次閱讀 安卓開發 Android開發 移動開發

這是一個系列文章,在這個系列里,我會按打造一個Material Design App的路線介紹所有應當掌握和值得掌握的系統組件。

你會在這些文章里了解到這些組件的使用和內部實現原理,以及它們背后所反映的Material Design的設計思想,希望你會喜歡。

前言

上一篇我介紹了有關Toolbar的知識點,在Toolbar的最左側,可以有一個導航按鈕的存在,它可以是一個向上鍵,可以是個菜單開關或者其他任何的樣式。

通常在App首頁,我們更多的見到它以一個菜單樣式的圖案呈現,點擊該按鈕,會從App的側邊彈出一個新頁面,我們稱之為“抽屜”。

在這篇文章里,我會 介紹抽屜在APP中的作用,以及如何通過 Drawerlayout&NavigationView來實現抽屜,順便說下我采用的抽屜菜單延伸至狀態欄的方法。

目錄

  1. Navigation Drawer簡介
  2. DrawerLayout詳解
  3. 代碼示例(一)
  4. NavigationView介紹
  5. 將DrawerLayout延伸至狀態欄
  6. 代碼示例(二)
  7. 幾句額外的

Navigation Drawer簡介

就像我一直強調的, Material Design的世界就是一個真實世界的縮影。一個優秀的Material Design組件,要么反映了真實世界里事物的功能和特性,要么反映了真實世界里的行為邏輯。

舉個例子,大家都使用過抽屜,我們通常會將 比較常用但又不需要每時每刻都使用 的東西放在抽屜里。在需要的時候,我們能準確且穩定地在指定地點找到;不需要的時候可以很好地隱藏和存放,不占用更多的可見空間。在我們的app里,也一定有數個這樣的操作入口:它們 比較常用但又不需要每時每刻都看見 。這時,我們自然就需要一個地方來存放它們,這就是我今天想要介紹的“抽屜導航欄”。

為了實現這樣的效果,Android官方提供了 DrawerLayout ,通過它我們便可以輕松創造出一個“抽屜”,下面就讓我們一起來詳細了解一下它。

DrawerLayout詳解

首先是使用,DrawerLayout的使用可以非常簡單,僅需要如下的XML代碼便能實現兩側都可以拉出抽屜的效果:

<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">
    <!-- 主內容 -->
    <LinearLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- 抽屜導航欄1 -->
    <RelativeLayout android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="100dp"
        android:layout_gravity="start"/>

    <!-- 抽屜導航欄2 -->
    <RelativeLayout android:id="@+id/right_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="end"/>

</android.support.v4.widget.DrawerLayout>

不過我們還是需要記住幾點:

  1. 在Drawerlayout中, 主內容視圖必須是第一個子視圖 。因為XML里是按層疊順序進行排序的,后面的內容會蓋過前面的內容,而抽屜視圖應位于頁面頂部。
  2. 抽屜視圖必須通過"android:layout_gravity"指定其重心位置 ,建議使用"start"&"end"來支持RTL(從右到左)語言。
  3. 主內容視圖的長寬都應“match_parent”,因為當抽屜收起時它代表整個UI界面。
  4. 抽屜部分的高度應設為match_parent,而寬度不應超過320dp,以便讓用戶仍可以看到部分主內容。

當然,僅僅只是這樣對我們的日常開發顯然是不夠的,我們需要對Drawerlayout有更多的細節處的掌控,對此Drawerlayout提供了簡便的API,下面我們就來了解一下。

常用方法詳解

  • openDrawer()方法用于打開“抽屜”,有四種參數形式:
    • (View drawerView): 打開傳入的抽屜視圖。
    • (int gravity): 打開傳入的相應gravity上的抽屜視圖。
    • (View drawerView, boolean animate): 打開傳入的抽屜視圖,第二個參數用于控制是否開啟視圖滑入動畫。
    • (int gravity, boolean animate): 打開傳入的相應gravity上的抽屜視圖,第二個參數用于控制是否開啟視圖滑入動畫。
  • closeDrawer()方法用于關閉“抽屜”,有四種參數形式:
    • closeDrawer(View drawerView): 關閉傳入的抽屜視圖。
    • closeDrawer(int gravity): 關閉傳入的相應gravity上的抽屜視圖。
    • closeDrawer(View drawView, boolean animate): 關閉傳入的抽屜視圖,第二個參數用于控制是否開啟視圖退出動畫。
    • closeDrawer(int gravity, boolean animate): 關閉傳入的相應gravity上的抽屜視圖,第二個參數用于控制是否開啟視圖退出動畫。
  • closeDrawers(): 關閉所有的抽屜視圖。
  • setDrawerTitle(int edgeGravity, CharSequence title): 依據傳入的gravity來給相應的Drawer設置title,設置title的目的是用于無障礙服務(Accessibility Service)。
  • CharSequence getDrawerTitle(int edgeGravity): 依據傳入的gravity來獲取相應Drawer的title。
  • setDrawerElevation(float elevation): 設置抽屜視圖的Z軸高度,帶來的視覺上的變化為 抽屜視圖的陰影發生了改變
  • float getDrawerElevation(): 用于獲取抽屜視圖的Z軸高度,返回值為float型。
  • boolean isDrawerOpen(View drawer / int drawerGravity): 根據傳入的參數判斷相應的Drawer是否處于開啟狀態。
  • boolean isDrawerVisible(View drawer / int drawerGravity): 根據傳入的參數判斷相應的Drawer當前在屏幕上是否可見。
  • setScrimColor(int color): 設置當抽屜打開時,未被抽屜遮住部分的顏色。
  • setDrawerLockMode(int lockMode / int lockMode,View drawerView / int lockMode, int edgeGravity): 該方法用于設置抽屜的鎖定模式,只傳入鎖定模式而不指定是哪個抽屜則會將兩側的抽屜都設置一遍。
    鎖定模式有四種:
    • LOCK_MODE_LOCKED_CLOSED:關閉抽屜的滑動操作并將抽屜收起
    • LOCK_MODE_LOCKED_OPEN:關閉抽屜的滑動操作并將抽屜打開
    • LOCK_MODE_UNDEFINED:將鎖定模式重新設置到默認狀態
    • LOCK_MODE_UNLOCKED:解鎖對抽屜的滑動操作鎖定
      注: 關閉抽屜的滑動操作即使

      通過滑動 打開/關閉 抽屜的操作失效

  • addDrawerListener(DrawerLayout.DrawerListener listener): 為Drawerlayout添加監聽器監聽抽屜的開啟關閉等事件。
  • removeDrawerListener(DrawerLayout.DrawerListener listener): 移除傳入的DrawerLayout的相應監聽器。

Drawer監聽器

上面的常用API介紹最后兩條提到了為DrawerLayout添加監聽器,下面就來介紹一下Drawer的監聽器——DrawerListener。

該接口提供了四個回調方法供復寫,分別是:

  • onDrawerOpened: 當抽屜處于完全打開的狀態時該方法會被回調
  • onDrawerClosed: 當抽屜處于完全關閉的狀態時該方法會被回調
  • onDrawerSlide: 當抽屜被滑動時該方法會回調
  • onDrawerStateChanged: 當抽屜的狀態發生變化時該方法會被回調

使用DrawerListener需要將以上四個方法都實現,但如果你只需要對其中的個別方法增加邏輯話,你可以使用 SimpleDrawerListener ,它繼承自DrawerListener,不需要你實現全部四個方法而是只需復寫你需要用到的方法。

ActionBarDrawerToggle

如果你的頁面包含了Toolbar(ActionBar),那么我更建議你使用ActionBarDrawerToggle。從它的名字也可以看出,這是當我們需要將ActionBar和Drawer結合使用的最佳途徑。

首先, ActionBarDrawerToggle該類實現了DrawerListener接口 ,所以其實你可以直接將它當作DrawerListener來使用,它能做到DrawerListener可以做的任何事。同時,會有一個抽屜樣式的indicator位于Toolbar(ActionBar)上,根據抽屜的打開和關閉,會有一個很自然的演變動畫給予用戶當前抽屜開或閉的明確提示。當然,如果你不想要那個圖標,也可以自己指定一個新的圖案(詳情見常用方法介紹)。

需要注意兩點:

  1. 該類應配合 onConfigurationChanged()onOptionsItemSelected() 使用,具體原因我直接在下面代碼的注釋里寫吧
  2. 如果使用了該類,應在 onPostCreate() 方法里調用 syncState() 來將指示器(indicator)的狀態和Drawer同步。

常用方法

  • boolean isDrawerIndicatorEnabled(): 返回當前指示器是否可用(可見)
  • setDrawerIndicatorEnabled(boolean enable): 設置指示器是否可用(可見)
  • setHomeAsUpIndicator(Drawable indicator / int resId):默認的指示器不可用時 為Drawer設置一個新的指示器
  • setToolbarNavigationClickListener(View.OnClickListener onToolbarNavigationClickListener): 為指示器綁定點擊事件監聽

代碼示例(一)

效果圖

效果視頻

Drawer詳解·效果視頻1—在線播放—優酷網,視頻高清在線觀看 http://v.youku.com/v_show/id_XMTgxNDU3ODc2OA==.html

activity_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_drawer_test"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <include layout="@layout/content_toolbar" />

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!--主內容-->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="設置蒙板顏色"
                android:textColor="@color/textPrimary"
                android:textSize="30sp" />

            <RadioGroup
                android:id="@+id/radio_group"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginBottom="30dp">

                <RadioButton
                    android:id="@+id/red_rbtn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="紅色"
                    android:textColor="@color/colorRed"
                    android:textSize="32sp" />

                <RadioButton
                    android:id="@+id/green_rbtn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="綠色"
                    android:textColor="@color/colorGreen"
                    android:textSize="32sp" />

                <RadioButton
                    android:id="@+id/purple_rbtn"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="紫色"
                    android:textColor="@color/colorPurpleLight"
                    android:textSize="32sp" />
            </RadioGroup>

        </LinearLayout>


        <!-- 抽屜導航欄1 -->
        <LinearLayout
            android:id="@+id/left_drawer"
            android:layout_width="400dp"
            android:layout_height="300dp"
            android:layout_gravity="start"
            android:background="@color/colorPrimaryLight"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="左側導航欄"
                android:textColor="@color/textPrimary"
                android:textSize="30sp" />

            <Button
                android:id="@+id/close_start_drawer_btn"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="關閉" />
        </LinearLayout>

        <!-- 抽屜導航欄2 -->
        <RelativeLayout
            android:id="@+id/right_drawer"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="end"
            android:background="@color/colorAccent">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="右側導航欄"
                android:textColor="@color/textPrimary"
                android:textSize="30sp" />
        </RelativeLayout>
    </android.support.v4.widget.DrawerLayout>

</LinearLayout>

Activity.java

public class DrawerTestActivity extends AppCompatActivity {

    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.radio_group)
    RadioGroup radioGroup;
    @BindView(R.id.drawer_layout)
    DrawerLayout drawerLayout;
    @BindView(R.id.close_start_drawer_btn)
    Button closeStartDrawerBtn;
    @BindView(R.id.left_drawer)
    LinearLayout leftDrawer;

    private ActionBarDrawerToggle mToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawer_test);
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);

        //配置ActionBarDrawerToggle
        toggleSettings();

        //配置RadioButton
        scrimColorSettings();
    }

    private void toggleSettings() {
        mToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(mToggle);
        mToggle.syncState();
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        mToggle.onConfigurationChanged(newConfig);
    }


    private void scrimColorSettings() {
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.red_rbtn:
                        drawerLayout.setScrimColor(getResources().getColor(R.color.colorRed));
                        break;
                    case R.id.green_rbtn:
                        drawerLayout.setScrimColor(getResources().getColor(R.color.colorGreen));
                        break;
                    case R.id.purple_rbtn:
                        drawerLayout.setScrimColor(getResources().getColor(R.color.colorPurpleLight));
                        break;
                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_drawer_test_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mToggle.onOptionsItemSelected(item)) {
            return true;
        }
        switch (item.getItemId()) {
            case R.id.action_drawers_close:
                drawerLayout.closeDrawers();
                break;
            case R.id.action_drawer_locked_close:
                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
                break;
            case R.id.action_drawer_locked_open:
                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN);
                break;
            case R.id.action_drawer_unlocked:
                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
                break;
            case R.id.action_drawer_reset:
                drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @OnClick(R.id.close_start_drawer_btn)
    public void onClick() {
        drawerLayout.closeDrawer(leftDrawer);
    }
}

NavigationView介紹

我們已經知道了如何使用DrawerLayout在側邊彈出頁面,接下來我們就要實現抽屜的具體效果了。那么在Material Design里,對抽屜的具體細節要求都是什么呢?看圖...

有如此細節的要求,自然應該有個實現這些細節的組件配合。為此,Google提供了NavigationView組件,將NavigationView與Drawerlayout配合使用,我們便可以輕松實現抽屜菜單。

NavigationView可分為兩部分——頭部布局和菜單點擊項布局。由于NavigationView使用比較簡單和呆板,我決定嘗試FAQ的方式來介紹這個組件的使用。

FAQ

  1. 如何指定頭布局和菜單點擊項布局?
    答:可在XML布局里使用 app:headerLayout="@layout/layout文件" 來指定頭布局,使用 app:menu="@menu/menu文件" 來指定菜單點擊項;
    在Java代碼里可以使用 inflateHeaderView(View view) 來指定頭布局,使用 inflateMenu(int resId) 來指定菜單布局。
  2. 如何監聽和處理菜單點擊事件?
    NavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                    //在此根據每個item的id處理相應的邏輯即可
                    return true;
                }
            });
  3. 如何改變菜單中圖標的顏色?
    答: app:itemIconTint="@color/顏色"
  4. 如何讓菜單中的圖標顏色還原成原本真實的顏色?
    答:

    NavigationView.setItemIconTintList(null)

  5. 如何設置頭部布局中的控件點擊事件?
    答:首先,使用NavigationView .getHeaderView(0) 獲得頭部布局,然后使用該布局的findViewById()獲取相應控件綁定點擊事件即可。

以上是使用NavigationView通常會遇到的問題,如果你還有其他的問題,歡迎在評論里交流。如果你還是對它的使用覺得云里霧里,那么看我最后的代碼吧~:blush:

將DrawerLayout延伸至狀態欄

這是一個引起過廣泛討論的問題,有關于這方面的文章和問題也有很多,當然也有不止一種解決方案,我采用的解決思路是:

  1. 將狀態欄設為透明
  2. 根據StatusBar的值為Toolbar設置相應的paddingTop
  3. 為作為根布局的DrawerLayout設置 setFitsSystemWindows(true)
  4. 為作為根布局的Drawerlayout設置

    setClipToPadding(false)

具體實現和效果請看下面的代碼示例。

代碼示例(二)

效果圖(Android 4.4)

效果圖(Android 7.0)

5.0以上都一樣,就不全放了。

layout.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:openDrawer="start">

    <include
        layout="@layout/content_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:background="@color/colorBlueGrey"
        app:headerLayout="@layout/nav_header_drawer_demo"
        app:itemBackground="@color/colorYellowLight"
        app:itemIconTint="@color/colorRed"
        app:itemTextColor="@color/colorGreen"
        app:menu="@menu/activity_drawer_demo_drawer" />

</android.support.v4.widget.DrawerLayout>


content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary"
            android:minHeight="?actionBarSize"
            android:paddingTop="@dimen/status_bar_height"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

    </android.support.design.widget.AppBarLayout>
</LinearLayout>

這里的dimen根據v23來區分即可。

Activity.java

public class DrawerDemoActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    ActionBarDrawerToggle toggle;

    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.nav_view)
    NavigationView navView;
    @BindView(R.id.drawer_layout)
    DrawerLayout drawerLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_drawer_demo);
        ButterKnife.bind(this);
        setSupportActionBar(toolbar);

        handlingStatusBar();
        toggleSettings();
        navView.setNavigationItemSelectedListener(this);

    }

    /**
     * 說明:DrawerLayout延伸至StatusBar并正常顯示
     */
    private void handlingStatusBar() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);

            drawerLayout.setFitsSystemWindows(true);
            drawerLayout.setClipToPadding(false);
        }
    }



    /**
     * 說明:配置ActionBarDrawerToggle
     */
    private void toggleSettings() {
        toggle = new ActionBarDrawerToggle(
                this, drawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawerLayout.addDrawerListener(toggle);
        toggle.syncState();
    }


    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camera) {

        } else if (id == R.id.nav_gallery) {

        } else if (id == R.id.nav_slideshow) {

        } else if (id == R.id.nav_manage) {

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        drawerLayout.closeDrawer(GravityCompat.START);
        return true;
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        toggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        toggle.onConfigurationChanged(newConfig);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (toggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

幾句額外的

從Bottom Navigation加入MD規范開始,我就看到過有關“拋棄Drawer”的說法,最近又看到了幾篇這樣的文章。其中不乏一些好的思考,但有些觀點還是過于激進了,甚至有些人云亦云。這里想分享下自己的看法:

首先,我們在 設計產品的時候,做出的一切決定都應該基于產品本身 :當前頁面的業務場景是什么,什么才是最符合需求的交互形式? 至于組件和界面只是產品的呈現手段和方式,最終目的都是為了給出一個最符合需求的產品。

再者,在學習和遵循Material Design時,除了知道怎么使用各種組件, 更應該理解這些組件真正的作用是什么,設計思想是什么 。只有這樣,我們才能在設計APP時做出更加正確的決定。 一個符合Material Design的APP絕不會是由各種MD組件隨意堆砌而成的。 至于說到拋棄Drawer,我認為更是完全沒有必要,不然你看看Android 7.0的設置界面?

下一篇我會介紹有關 Bottom Navigation 的知識點,也算是個對比。希望看完這兩篇后,能夠幫助你在構思界面時做出更好的決定。

參考文章

Creating a Navigation Drawer | Android官方文檔

DrawerLayout | Android官方文檔

Why would I want to fitsSystemWindows?

http:// weixin.qq.com/r/yTgrM-D ESK03rbRQ923b (二維碼自動識別)

 

 

來自:https://zhuanlan.zhihu.com/p/22970240

 

 本文由用戶 ccheima 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!