AndroidStudyDemo之Android6.x新控件介紹(二)

Android6.x新控件介紹(二)

作者:李旺成

時(shí)間:2016年4月22日


接上篇:AndroidStudyDemo之Android6.x新控件介紹(一)

四、TabLayout

先看效果:

TabLayout 使用演示

簡介

TabLayout 就是用來做選項(xiàng)卡切換這一類效果的控件,在兼容包中提供。對于 Tab 的實(shí)現(xiàn) Google 上提供過不少方案,先有 TabHost;然后在 Android 3.x 上又出現(xiàn)了 ActionBar 提供的 Tab;現(xiàn)在有了更好的實(shí)現(xiàn),那就是使用用 TabLayout。

當(dāng)然,還有非常多的各種第三方開源庫來實(shí)現(xiàn) Tab,例如:JakeWharton 大神開源的組件 ViewPagerIndicator 相信很多人都用過。

  • Tabs 選項(xiàng)卡,效果類似網(wǎng)易新聞客戶端的 Tab
  • Google 官方實(shí)現(xiàn)的 TabPageIndicator

先看看官方的介紹:

TabLayout 簡介

先看繼承結(jié)構(gòu)(習(xí)慣從繼承結(jié)構(gòu)來學(xué)習(xí)和分析如何使用新控件),和 TabPageIndicator 一樣繼承自 HorizontalScrollView,這個(gè)很好理解,Tab 的數(shù)量一多,那就需要橫向滑動,直接繼承自 HorizontalScrollView 來實(shí)現(xiàn)會省事很多(不會偷懶的程序員不是好程序員,呵呵,不記得誰說的了,不發(fā)表個(gè)人意見)。

對于控件還需要關(guān)注的一點(diǎn)就是它的屬性(在 Layout 中使用的),那么來看看官方對 TabLayout 的特有屬性的介紹:

TabLayout 屬性

坑!竟然沒有對 TabLayout 特有屬性的介紹,那只能先看看它提供的方法了:

TabLayout 方法

好像也沒有太多可參考的,那直接用起來。

簡單使用

1、導(dǎo)入兼容包

compile 'com.android.support:design:23.3.0'

2、直接使用示例

直接使用示例

TabLayout 繼承自 HorizontalScrollView,那先當(dāng)作 HorizontalScrollView 試試:
在 Layout 中簡單使用,沒有使用 TabLayout 特有的屬性:

<android.support.design.widget.TabLayout
    android:id="@+id/tl_test"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

在 Java 代碼中使用:

private void addTab() {
    mTabsNum += 1;
    TabLayout.Tab tab = mTestTL.newTab().setText("TAB" + mTabsNum);
    mTestTL.addTab(tab);
}

private void removeFirstTab() {
    int count = mTestTL.getTabCount();
    if (count <= 0) return;
    mTestTL.removeTabAt(0);
}

private void removeLastTab() {
    int count = mTestTL.getTabCount();
    if (count <= 0) return;
    mTestTL.removeTabAt(count - 1);
}

private void removeAllTabs() {
    int count = mTestTL.getTabCount();
    if (count <= 0) return;
    mTabsNum = 0;
    mTestTL.removeAllTabs();
}

上面示例代碼演示了 Tab 的添加和刪除,簡單介紹下 Tab 類和 addTab() 方法:

  • Tab 類:這是 TabLayout 中的靜態(tài)內(nèi)部類,看下源碼,
Tab 靜態(tài)內(nèi)部類

構(gòu)造方法是 private 的,不能直接 new 對象,注釋中提示可以使用 TabLayout 的 newTab() 方法來創(chuàng)建實(shí)例。

  • addTab() 方法:addTab() 有四個(gè)重載方法,那就看參數(shù)最多的那個(gè)吧!(參數(shù)最多的都會用了,其他的就很簡單了)
addTab() 方法

第一個(gè)參數(shù) tab,就是 Tab 類的實(shí)例;第二個(gè)參數(shù) position,用于指定加入的 Tab 需要插入的位置,這里需注意,調(diào)用該方法之前最好通過 getTabCount() 方法獲取當(dāng)前 TabLayout 中所擁有的 Tab 總數(shù),如果 position + 1 大于總 TabLayout 中的 Tab 總數(shù)會導(dǎo)致數(shù)組越界(這個(gè)應(yīng)該不難理解);第三個(gè)參數(shù) setSelected,用于指定新加入的 Tab 是否為選中狀態(tài)。

3、配合 ViewPager 使用

配合 ViewPager 使用

TabLayout 是個(gè)指示器,確切的說是 ViewPager 的指示器,所以更常見的使用場景是配合 ViewPager 來使用。
在 Layout 中使用:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.diygreen.android6new.newwidget2.TabLayoutDemo3Activity">
    <android.support.design.widget.TabLayout
        android:id="@+id/tl_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scrollbars="none"/>
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/tl_bottom"
        android:scrollbars="none" />
</RelativeLayout>

將把 TabLayout 當(dāng)作普通的布局使用即可。

在 Java 代碼中:

private void initData() {
    int size = mTitleArr.length;
    mViewList = new ArrayList<>(size);
    // 添加 Tab,初始化 View 列表
    for (int i = 0; i < size; i++) {
        mTitleTL.addTab(mTitleTL.newTab().setText(mTitleArr[i]));
        View view = LayoutInflater.from(this).inflate(R.layout.item_tablayoutdemo2_vp, null);
        TextView tv = (TextView) view.findViewById(R.id.tv_text);
        tv.setText(mTitleArr[i]);
        mViewList.add(view);
    }
    mAdapter = new TabLayoutDemo2PagerAdapter(mViewList);

    // 填充 ViewPager
    mContentVP.setAdapter(mAdapter);
    // 給ViewPager添加監(jiān)聽
    mContentVP.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTitleTL));
    // 設(shè)置setOnTabSelectedListener
    mTitleTL.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            // 切換到指定的 item
            mContentVP.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
}

要實(shí)現(xiàn) TabLayout 與 ViewPager 的聯(lián)動,有兩個(gè)關(guān)鍵方法:
// 給 ViewPager 添加頁面改變監(jiān)聽
addOnPageChangeListener()
// 設(shè)置 Tab 選擇監(jiān)聽
setOnTabSelectedListener()
上面代碼中都做了示例,使用也很簡單。

說明:還有另一種方式來實(shí)現(xiàn)聯(lián)動,使用的是 setupWithViewPager() 方法
// 設(shè)置 TabLayout 與 ViewPager 聯(lián)動
setupWithViewPager():該方法在 TabLayoutDemo4Activity.java 中使用了,會在下面做說明。

4、實(shí)現(xiàn)底部 Tab

底部 Tab

這個(gè)很簡單,直接看布局文件就可以了。

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.diygreen.android6new.newwidget2.TabLayoutDemo3Activity">
    <android.support.design.widget.TabLayout
        android:id="@+id/tl_bottom"
        style="@style/DIYTabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"/>
    <android.support.v4.view.ViewPager
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/tl_bottom"
        android:scrollbars="none" />
</RelativeLayout>

-_-^,把 TabLayout 放到 ViewPager 下面即可...

5、自定義 TabLayout 樣式

自定義樣式示例

TabLayout 的特有屬性:

TabLayout 特有屬性

看著好像不少,但仔細(xì)看一下,其實(shí)不多,而且這些屬性名稱大部分應(yīng)該都認(rèn)識,或者說在其他控件中使用過。

沒有文檔說明,那就看著效果來簡單解釋下這些屬性,還是那句話先用起來。

效果如圖:

TabLayout 自定義樣式.png

首先,在 style 文件中定義:

<!-- 自定義 TabLayout 樣式 -->
<style name="DIY.TabLayout" parent="Widget.Design.TabLayout">
    <item name="paddingEnd">10dp</item>
    <item name="paddingStart">10dp</item>
    <item name="tabBackground">@color/colorPrimaryDark</item>
    <item name="tabContentStart">10dp</item>
    <item name="tabGravity">center</item>
    <item name="tabIndicatorColor">#999900</item>
    <item name="tabIndicatorHeight">6dp</item>
    <item name="tabMaxWidth">@dimen/tab_max_width</item>
    <item name="tabMinWidth">@dimen/tab_min_width</item>
    <item name="tabMode">scrollable</item>
    <item name="tabPaddingBottom">2dp</item>
    <item name="tabPaddingEnd">10dp</item>
    <item name="tabPaddingStart">10dp</item>
    <item name="tabPaddingTop">15dp</item>
    <item name="tabSelectedTextColor">#ffcc00</item>
    <item name="tabTextAppearance">@style/DIY.TabTextAppearance</item>
    <item name="tabTextColor">#000066</item>
</style>
<!-- 自定義 TabText 的外觀 -->
<style name="DIY.TabTextAppearance" parent="TextAppearance.Design.Tab">
    <item name="android:textSize">14sp</item>
    <item name="android:textColor">#006600</item>
    <item name="textAllCaps">false</item>
</style>

然后,在 Layout 中使用樣式

<android.support.design.widget.TabLayout
    android:id="@+id/tl_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/DIY.TabLayout"/>

有幾個(gè)屬性要解釋一下:

  • tabGravity:用來設(shè)置 TabLayout 的布局方式,只有兩個(gè)可選值fill 和 center,默認(rèn)值是 fill
  • tabIndicatorColor:用來設(shè)置底部指示器的顏色
  • tabIndicatorHeight:用來設(shè)置底部指示器的高度
  • tabMode:用來設(shè)置 TabLayout 的布局模式,有兩個(gè)取值
    fixed:固定不可滾動
    scrollable: 可滾動的

對應(yīng)的 Java 方法:

  • setTabGravity()
  • setSelectedTabIndicatorColor()
  • setSelectedTabIndicatorHeight()
  • setTabMode():MODE_FIXED 或 MODE_SCROLLABLE

其他的屬性都是用于設(shè)置 Tab 中文本的屬性,這基本上可以參考 TextView。

6、給 TabLayout 加角標(biāo)

加角標(biāo)示例

其實(shí)就是利用 TabLayout.Tab 的 setCustomView() 方法,最好自己維護(hù)好為 Tab 設(shè)置的 CustomView 列表,以便更新數(shù)據(jù)。

簡單的示例:

private void initData() {
    int size = mTitleArr.length;
    mTabItemViewList = new ArrayList<>(size);
    mViewPagerViewList = new ArrayList<>(size);
    // 添加 Tab,初始化 View 列表
    for (int i = 0; i < size; i++) {
        View tabView = LayoutInflater.from(this).inflate(R.layout.item_tablayout_item, null);
        TextView tabViewTV = (TextView) tabView.findViewById(R.id.tv_tab);
        tabViewTV.setText(mTitleArr[i]);
        mTabItemViewList.add(tabView);

        View vpView = LayoutInflater.from(this).inflate(R.layout.item_tablayoutdemo2_vp, null);
        TextView viViewTV = (TextView) vpView.findViewById(R.id.tv_text);
        viViewTV.setText(mTitleArr[i] + i);
        mViewPagerViewList.add(vpView);
    }
    mAdapter = new TabLayoutDemo2PagerAdapter(mViewPagerViewList);

    // 填充 ViewPager
    mContentVP.setAdapter(mAdapter);
    mTitleTL.setupWithViewPager(mContentVP);
    size = mTitleTL.getTabCount();
    for (int i = 0; i < size; i++) {
        TabLayout.Tab tab = mTitleTL.getTabAt(i);
        if (tab != null) {
            tab.setCustomView(mTabItemViewList.get(i));
        }
    }
    mContentVP.setCurrentItem(1);
}

注意事項(xiàng)

1、關(guān)于 TabMode
如果你發(fā)現(xiàn)你的 TabLayout 不能滾動,那么可能是沒有設(shè)置 TabMode 為 MODE_SCROLLABLE 的緣故

2、關(guān)于 remove 方法
TabLayout 的 removeXxx 方法沒有什么問題,這里要說的是當(dāng) TabLayout 與 ViewPager 一起使用的時(shí)候,ViewPager 不能同步刷新的問題。設(shè)想一下你在刪除 Tab 的同時(shí)希望刪除該 Tab 下 ViewPager 中的相應(yīng)頁面,這時(shí)你修改 ViewPager 的數(shù)據(jù)源,然后調(diào)用 ViewPager Adapter 的 notifyDataSetChanged()(ListView 中是這個(gè)思路,并且沒什么問題),你會發(fā)現(xiàn)結(jié)果并不是你料想的那般。

對于該問題,不是一兩句話可以說清楚的,你可以 Google 一下“ViewPager notifyDataSetChanged 無效”,有一大堆文章在討論這個(gè)問題,但是都不能覆蓋所有場景。所以,打算專門寫一篇文章來討論這個(gè)問題。

3、關(guān)于 setupWithViewPager 方法
在設(shè)置 TabLayout 與 ViewPager 聯(lián)動的時(shí)候,有一種方式是,分別調(diào)用 ViewPager 的 addOnPageChangeListener() 方法關(guān)聯(lián) TabLayout,和 TabLayout 的 setOnTabSelectedListener() 方法關(guān)聯(lián) ViewPager;這樣才能達(dá)到聯(lián)動的目的。

還有一種方式是通過 TabLayout 的 setupWithViewPager() 方法,剛開始以為直接調(diào)用該方法即可完成聯(lián)動(就是第一種方式的其他代碼都不動,只是刪除關(guān)聯(lián)用到的兩個(gè)方法)。試了一下,結(jié)果發(fā)現(xiàn) Tab 的文本沒有顯示出來,下面的線條有了,而且可以聯(lián)動。坑!有沒有,我沒打算去分析里面的原因了,直接給出正確的添加 Tab 的方式,注意是調(diào)用 setupWithViewPager() 方法的時(shí)候:

private void initData() {
    int size = mTitleArr.length;
    mViewList = new ArrayList<>(size);
    // 初始化 View 列表
    for (int i = 0; i < size; i++) {
        View view = LayoutInflater.from(this).inflate(R.layout.item_tablayoutdemo2_vp, null);
        TextView tv = (TextView) view.findViewById(R.id.tv_text);
        tv.setText(mTitleArr[i]);
        mViewList.add(view);
    }
    mAdapter = new TabLayoutDemo2PagerAdapter(mViewList);

    // 填充 ViewPager
    mContentVP.setAdapter(mAdapter);
    mTitleTL.setupWithViewPager(mContentVP);
    size = mTitleTL.getTabCount();
    for (int i = 0; i < size; i++) {
        TabLayout.Tab tab = mTitleTL.getTabAt(i);
        if (tab != null) {
            tab.setText(mTitleArr[i]);
        }
    }
    mContentVP.setCurrentItem(1);
}

4、關(guān)于 setScrollPosition 方法
該方法是用來設(shè)置 Tab 下那條線的位置的,來看下方法簽名:

public void setScrollPosition(int position, float positionOffset, boolean updateSelectedText)

這里想說明的問題是,該方法使用的時(shí)候容易引起誤會,對第二個(gè)參數(shù)不理解。

第一個(gè)參數(shù)表示當(dāng)前 Tab 的位置,第二個(gè)參數(shù)是偏移值,該值的取值范圍是0到1的一個(gè)半開區(qū)間,最后一個(gè)參數(shù)表示是否置移動后位置所對應(yīng)的Tab為選中狀態(tài)。這里要說明的是 positionOffset 這個(gè)參數(shù)是一個(gè)倍數(shù)值,這里不打算分析其實(shí)現(xiàn),有興趣的可以去看看這篇文章TabLayout:另一種Tab的實(shí)現(xiàn)方式,里面解釋得不錯(cuò)。

5、setTabGravity 方法
上面介紹了該方法的作用,要注意的是 setTabGravity 方法只有在 Mode 為 MODE_FIXED 的情況下才有用。

6、setTabTextColors 方法無效?
setTabTextColors 當(dāng)然不是說真的無效,場景是這樣的,如果你在 addTab 方法之后,再來調(diào)用該方法,這時(shí)會看到,該方法沒有起作用(TabLayout 的 Bug 有沒有?)。

當(dāng)然這也不是什么無解的問題,我們完全可以通過使用自定義 View 的來作為 TabLayout 的 Item,那么這個(gè)控制權(quán)就全部在我們手上了。

小結(jié)

TabLayout 的介紹就到這里了,使用比較簡單。

五、NavigationView

先看看效果:

NavigationView 示例

簡介

NavigationView 是兼容包中提供的用來實(shí)現(xiàn)導(dǎo)航菜單界面的新控件,看看該控件的特點(diǎn):

  • 導(dǎo)航抽屜,被設(shè)計(jì)用于應(yīng)用導(dǎo)航
  • 提供了一種通用的導(dǎo)航方式,體現(xiàn)了設(shè)計(jì)的一致性
  • 導(dǎo)航菜單框架,使用menu資源填充數(shù)據(jù)
  • 可以更簡單高效的實(shí)現(xiàn)導(dǎo)航菜單

來看下官方介紹:

NavigationView 類

NavigationView 繼承自 Framelayout,從繼承結(jié)構(gòu)來看,參考意義不大,好在官方給了示例代碼,那了解下它特有的屬性,然后用起來再說。

NavigationView 的特有屬性:


NavigationView 特有屬性

簡單使用

1、導(dǎo)入兼容包

compile 'com.android.support:design:23.3.0'

2、在 Layout 中使用

<?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"
    android:id="@+id/dl_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <!-- Content -->
    <FrameLayout
        android:id="@+id/fl_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.support.v7.widget.Toolbar
            android:id="@+id/tb_title"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:layout_scrollFlags="scroll|enterAlways" />
    </FrameLayout>

    <!-- Drawer -->
    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_left"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer_menu"/>
</android.support.v4.widget.DrawerLayout>

3、定義 headerLayout
在上面的 NavigationView 中使用了 app:headerLayout,該屬性不是必須的,這里是為了更完整的演示如何使用。這個(gè) headerLayout 就是一個(gè)自定義的布局,如:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="170dp"
    android:theme="@style/ThemeOverlay.AppCompat.Dark"
    android:background="@mipmap/bg_drawer_header">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:id="@+id/iv_headimg"
        android:src="@mipmap/ic_logo"
        android:layout_above="@+id/switch_online"
        android:layout_alignParentStart="true" />
    <Switch
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/switch_online"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:checked="false" />
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="DIY-green"
        android:id="@+id/tv_name"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>

4、定義 menu
NavigationView 的 app:menu 屬性用于指定自定義的菜單布局文件,一般是必選項(xiàng),當(dāng)然也可以在代碼中動態(tài)設(shè)置。這個(gè) menu 也不是什么新東西,直接看代碼就明白了:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group
        android:checkableBehavior="single">
        <item
            android:id="@+id/drawer_home"
            android:checked="true"
            android:icon="@mipmap/ic_alarm_add_black"
            android:title="Alarm"/>
        <item
            android:id="@+id/drawer_favourite"
            android:icon="@mipmap/ic_cast_connected_black"
            android:title="Connected"/>
        <!-- 為 Item 添加子菜單,實(shí)現(xiàn)分組 -->
        <item
            android:id="@+id/section"
            android:icon="@mipmap/ic_more_horiz_grey"
            android:title="Group">
            <menu>
                <group
                    android:checkableBehavior="single">
                <item
                    android:id="@+id/drawer_downloaded"
                    android:icon="@mipmap/ic_computer_grey"
                    android:title="Computer"/>
                <item
                    android:id="@+id/drawer_more"
                    android:icon="@mipmap/ic_border_color_grey"
                    android:title="Border"/>
                </group>
            </menu>
        </item>
        <item
            android:id="@+id/drawer_settings"
            android:icon="@mipmap/ic_fullscreen_black"
            android:title="FullScreen"/>
    </group>
</menu>

上面示例代碼中使用了 android:checkableBehavior="single" 屬性,是為了保證該 Group 下的 Item 為單選狀態(tài),這個(gè)會在注意事項(xiàng)里面詳細(xì)介紹。

可以通過為 Item 添加子菜單來實(shí)現(xiàn)帶有頭部的分組效果,注意一下分組的效果,在該分組的最上面會添加一條分隔;還有就是雖然示例代碼中給分組 Item 設(shè)置了 icon 屬性,但是并不會顯示。

5、設(shè)置 Menu Item 的點(diǎn)擊監(jiān)聽
直接使用 NavigationView 的 setNavigationItemSelectedListener() 方法即可:

mLeftNavigation.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override public boolean onNavigationItemSelected(MenuItem menuItem) {
        Snackbar.make(mContentView, menuItem.getTitle() + " pressed", Snackbar.LENGTH_LONG).show();
        menuItem.setChecked(true);
        mRootDL.closeDrawers();
        return true;
    }
});

NavigationView 的封裝性比較高,使用起來比較簡單,代碼不多,但是有些小細(xì)節(jié)需要注意。

注意事項(xiàng)

將 NavigationView 布局的內(nèi)容延伸到狀態(tài)欄實(shí)實(shí)現(xiàn)

先看下效果:

將布局內(nèi)容延伸到狀態(tài)欄實(shí)

圖中使用紅線條圈出來的就是將 NavigationView 布局的內(nèi)容延伸到狀態(tài)欄實(shí)的效果。

要實(shí)現(xiàn)該效果,有幾個(gè)要注意的地方:

  1. android:fitsSystemWindows 屬性
    最好將 DrawerLayout 和 NavigationView 的該屬性都設(shè)置為 true
  2. values-v21 中的 style
<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- 該屬性必須 -->
    <item name="android:windowTranslucentStatus">true</item>
    <item name="android:colorControlHighlight">@color/colorPrimary</item>

    <item name="android:windowSharedElementsUseOverlay">false</item>
</style>

要實(shí)現(xiàn)上述效果,按照這兩步走就 OK 了。關(guān)于該問題更進(jìn)一步的討論,可以參考知乎上的一個(gè)提問: Android 5.0 如何實(shí)現(xiàn)將布局的內(nèi)容延伸到狀態(tài)欄實(shí)?,在這里就不展開討論了。

有分組時(shí) Item 單選實(shí)現(xiàn)

上面說了,將 Group 中的 android:checkableBehavior 設(shè)置為 "single" 是為了實(shí)現(xiàn)菜單項(xiàng)的單選。

但現(xiàn)在有個(gè)問題,如果在菜單項(xiàng)下面有子菜單,也就是有分組的情況時(shí);如果僅在最外層使用 group 標(biāo)簽,如下

<group
    android:checkableBehavior="single">
        ...
</group>

包裹所有的菜單項(xiàng)和分組的話,是達(dá)不到單選效果的。(這里就不演示了,你可以自行修改示例項(xiàng)目去看看效果)

我的解決方案是將分組的 Item 也用 group 標(biāo)簽包裹,當(dāng)然也得將 checkableBehavior 屬性設(shè)置為 “single”,看代碼:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 最外層使用 group 標(biāo)簽 --->
    <group
        android:checkableBehavior="single">
        <item
            android:id="@+id/drawer_home"
            android:checked="true"
            android:icon="@mipmap/ic_alarm_add_black"
            android:title="Alarm"/>
        ...
        <item
            android:id="@+id/section"
            android:icon="@mipmap/ic_more_horiz_grey"
            android:title="Group">
            <menu>
                <!-- 在分組中使用 group 標(biāo)簽 --->
                <group
                    android:checkableBehavior="single">
                <item
                    android:id="@+id/drawer_downloaded"
                    android:icon="@mipmap/ic_computer_grey"
                    android:title="Computer"/>
                <item
                    android:id="@+id/drawer_more"
                    android:icon="@mipmap/ic_border_color_grey"
                    android:title="Border"/>
                </group>
            </menu>
        </item>
        ...
    </group>
</menu>

NavigationView 配合 DrawerLayout 來實(shí)現(xiàn)側(cè)滑菜單是不錯(cuò)的選擇,更關(guān)鍵的是這些都是 Google 官方提供的控件,兼容性方面會好點(diǎn)。

小結(jié)

本來打算只用兩篇來介紹 Android 6.x 中的新控件的,但是考慮到有不少控件都是 MaterialDesign 中的比較重要的成員,所以,會稍微介紹詳細(xì)點(diǎn)。

Android 6.x 的新控件介紹還有一篇,這將是 Android 6.x 系列介紹的最后一篇了。
未完待續(xù)...

項(xiàng)目地址

GitHub

附件

Andoid6思維導(dǎo)圖

參考

TabLayout:另一種Tab的實(shí)現(xiàn)方式
使用Desgin包組件 TabLayout助你輕松打造網(wǎng)易搜狐頂部導(dǎo)航欄
Material Design之NavigationView和DrawerLayout實(shí)現(xiàn)側(cè)滑菜單欄
使用TabLayout實(shí)現(xiàn)底部Tab布局
android design library提供的TabLayout的用法
Android Design Support Library初探,NavigationView實(shí)踐
Android 5.0 如何實(shí)現(xiàn)將布局的內(nèi)容延伸到狀態(tài)欄實(shí)?
Design Support Library (I): Navigation View的使用

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

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