第一行代碼(十二)

第十二章主要講了 Material Design 的一些用法

一、Maternal Design 介紹

??Android 平臺(tái)的界面風(fēng)格長(zhǎng)期難以統(tǒng)一违寞,為了解決這個(gè)問題纵潦,Google 推出了全新的界面設(shè)計(jì)語(yǔ)言--Material Design.
??從 Android5.0開始,就將所有內(nèi)置的應(yīng)用都使用 Material Design 風(fēng)格來(lái)進(jìn)行設(shè)計(jì)听绳。谷歌在2015年 Google I/O 大會(huì)上推出了 Design Support 庫(kù)颂碘。

二、Toolbar

??每個(gè)活動(dòng)最頂部的那個(gè)標(biāo)題欄其實(shí)就是 ActionBar椅挣,不過(guò) ActionBar 由于其設(shè)計(jì)原因头岔,被限定只能位于活動(dòng)頂部,從而不能實(shí)現(xiàn)一些 Material Design 的效果鼠证,因此官方已經(jīng)不再建議使用 ActionBar 了峡竣。
??ToolBar 的強(qiáng)大之處在于,它不僅繼承了 ActionBar 的所有功能名惩,而且靈活性很高澎胡,可以配合其他控件一起來(lái)完成一些 Material Design 的效果。

注意:任何一個(gè)新建的項(xiàng)目娩鹉,默認(rèn)都會(huì)顯示 ActionBar 的攻谁,這個(gè) ActionBar 是根據(jù)項(xiàng)目中指定的主題來(lái)顯示的。打開清單文件弯予,找到 <application>標(biāo)簽中有一個(gè) android:theme 屬性戚宦,并且指定了一個(gè) AppTheme 主題。

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

</resources>

??這個(gè) DarkActionBar 就是一個(gè)深色的 ActionBar 主題锈嫩,項(xiàng)目中自帶的 ActionBar 就是因?yàn)橹付诉@個(gè)主題才出現(xiàn)的受楼。但是我們現(xiàn)在要使用 ToolBar,所以要指定一個(gè)不帶 ActionBar 的主題呼寸,通常有 Theme.AppCompat.NoActionBar 和 Theme.AppCompat.Light.NoActionBar 這兩種主題艳汽,其中 Theme.AppCompat.NoActionBar 表示深色主題,他會(huì)將界面的主體顏色設(shè)置成深色对雪,陪襯顏色設(shè)成淡色河狐。而 Theme.AppCompat.Light.NoActionBar 表示淡色主題,它會(huì)將界面的主體顏色設(shè)置成淡色瑟捣,陪襯顏色設(shè)成深色馋艺。
??觀察一下 AppTheme 中的屬性重寫,這里重寫了 colorPrimary迈套、colorPrimaryDark 和 colorAccent 這3個(gè)屬性的顏色捐祠。

image.png

其他:

  • 1.colorPrimary:應(yīng)用的主要色調(diào),actionBar默認(rèn)使用該顏色桑李,Toolbar導(dǎo)航欄的底色
  • 2.colorPrimaryDark:應(yīng)用的主要暗色調(diào)踱蛀,statusBarColor默認(rèn)使用該顏色
  • 3.statusBarColor:狀態(tài)欄顏色窿给,默認(rèn)使用colorPrimaryDark
  • 4.windowBackground:窗口背景顏色
  • 5.navigationBarColor:底部欄顏色
  • 6.colorForeground:應(yīng)用的前景色,ListView的分割線星岗,switch滑動(dòng)區(qū)默認(rèn)使用該顏色
  • 7.colorBackground:應(yīng)用的背景色填大,popMenu的背景默認(rèn)使用該顏色
  • 8.colorAccent:CheckBox,RadioButton俏橘,SwitchCompat等一般控件的選中效果默認(rèn)采用該顏色
  • 9.colorControlNormal:CheckBox允华,RadioButton,SwitchCompat等默認(rèn)狀態(tài)的顏色寥掐。
  • 10.colorControlHighlight:控件按壓時(shí)的色調(diào)
  • 11.colorControlActivated:控件選中時(shí)的顏色靴寂,默認(rèn)使用colorAccent
  • 12.colorButtonNormal:默認(rèn)按鈕的背景顏色
  • 13.editTextColor:默認(rèn)EditView輸入框字體的顏色。
  • 14.textColor:Button召耘,textView的文字顏色
  • 15.textColorPrimaryDisableOnly:RadioButton checkbox等控件的文字
  • 16.textColorPrimary:應(yīng)用的主要文字顏色百炬,actionBar的標(biāo)題文字默認(rèn)使用該顏色
  • 17.colorSwitchThumbNormal:switch thumbs 默認(rèn)狀態(tài)的顏色

??使用了 NoActionBar 主題后,我們已經(jīng)將 ActionBar 隱藏起來(lái)了污它,接下來(lái)就要使用 ToolBar 代替 ActionBar 了剖踊。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
        
    </android.support.v7.widget.Toolbar>

</FrameLayout>

這里首先記得添加 xmlns:app 指定命名空間,因?yàn)?Material Design 是在 Android5.0系統(tǒng)中才出現(xiàn)的衫贬,而很多 Material 屬性在5.0之前的系統(tǒng)中并不存在德澈,為了兼容之前的老系統(tǒng),我們不能使用 android:attribute 這樣的寫法了固惯,就要使用 app:attribute 的寫法梆造。

我們使用了 ToolBar 控件,該控件是 appcompat-v7庫(kù)提供的葬毫,高度指定為 ActionBar 的高度镇辉,背景色設(shè)置為 colorPrimary。接下來(lái)贴捡,我們?cè)O(shè)置了主題忽肛,因?yàn)槲覀冊(cè)?style.xm里面將程序的主題設(shè)置成了淡色主題,因此 ToolBar 也是淡色主題烂斋,ToolBar 上的元素就會(huì)自動(dòng)使用深色主題麻裁,看起來(lái)很難看,為了讓 ToolBar 單獨(dú)使用深色主題源祈,我們就使用了 theme 為 ToolBar 單獨(dú)指定了一個(gè)主題:ThemeOverlay.AppCompat.Dark.ActionBar,但是這樣又會(huì)有一個(gè)問題色迂,如果 ToolBar 中有菜單按鈕香缺,彈出的菜單項(xiàng)會(huì)變成深色主題,又變得很難看歇僧,于是使用了 app:popupTheme屬性單獨(dú)將彈出的菜單指定成了淡色主題图张。

        Toolbar toolBar = (Toolbar) findViewById(R.id.toolbar);
        /*
            這句話的作用是:既使用了 ToolBar锋拖,又讓它的外觀和功能都和 ActionBar 一致
         */
        setSupportActionBar(toolBar);
        <activity android:name=".MaterialDesignActivity"
            android:label="Material Design">
            <!--這里我們?yōu)?Activity 指定了一個(gè) label,作用就是讓在 ToolBar 中顯示標(biāo)題-->
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

??接下來(lái)我們給 ToolBar 添加一個(gè) action 按鈕


image.png

image.png
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/backup"
        android:icon="@mipmap/ic_launcher"
        android:title="Backup"
        app:showAsAction="always" />

    <item
        android:id="@+id/delete"
        android:icon="@mipmap/ic_launcher"
        android:title="delete"
        app:showAsAction="ifRoom" />

    <item
        android:id="@+id/settings"
        android:icon="@mipmap/ic_launcher"
        android:title="settings"
        app:showAsAction="never" />
</menu>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!--使用 showAsAction 來(lái)指定按鈕的顯示位置 祸轮,
        這里之所以使用 app 命名空間兽埃,是為了能夠
        兼容低版本-->

    <!-- always 表示永遠(yuǎn)顯示在 ToolBar 上,如果屏幕空間不夠則不顯示 -->
    <item
        android:id="@+id/backup"
        android:icon="@mipmap/ic_launcher"
        android:title="Backup"
        app:showAsAction="always" />

    <!--ifRoom 表示如果屏幕空間足夠就顯示在 ToolBar 上适袜,
        不夠的話就顯示在菜單當(dāng)中-->

    <item
        android:id="@+id/delete"
        android:icon="@mipmap/ic_launcher"
        android:title="delete"
        app:showAsAction="ifRoom" />

    <!-- never 表示永遠(yuǎn)顯示在菜單當(dāng)中-->
    <item
        android:id="@+id/settings"
        android:icon="@mipmap/ic_launcher"
        android:title="settings"
        app:showAsAction="never" />
</menu>

注意:ToolBar 中的 action 按鈕只會(huì)顯示圖標(biāo)柄错,菜單中的 action 按鈕只會(huì)顯示文字。

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.backup:
                Toast.makeText(this, "backUp", Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this, "delete", Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this, "settings", Toast.LENGTH_SHORT).show();
                break;
            default:
                break;
        }
        return true;
    }

ToolBar 使用總結(jié):

    1. 首先要設(shè)置應(yīng)用主題是 NoActionBar 的
    1. 然后在布局文件中要使用 app 命名空間
    1. 給 ToolBar 設(shè)置高度為?attr/actionBarSizeActionBar 的高度苦酱,背景色設(shè)置為?attr/colorPirmary
    1. 根據(jù)程序主體顏色售貌,設(shè)置 ToolBar 的 theme 主體顏色(與程序主體顏色相反),android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"疫萤,然后設(shè)置彈出的菜單主體顏色(與程序主體顏色相同)app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
    1. ToolBar 最左側(cè)有一個(gè)按鈕颂跨,叫做 HomeAsUp,默認(rèn)是一個(gè)向左的箭頭扯饶,該按鈕的 id 永遠(yuǎn)都是 android.R.id.home

二恒削、DrawerLayout(滑動(dòng)菜單)

??所謂滑動(dòng)菜單,就是將一些菜單隱藏起來(lái)尾序,不放在主屏幕上钓丰,然后可以通過(guò)滑動(dòng)的方式將菜單顯示出來(lái)。我們可以借助 DrawerLayout 來(lái)實(shí)現(xiàn)這種效果蹲诀。
??首先 DrawerLayout (support.v4庫(kù)提供)是一個(gè)布局斑粱,在布局中允許放入兩個(gè)直接子控件,第一個(gè)子控件是主屏幕中顯示的內(nèi)容脯爪,第二個(gè)控件是滑動(dòng)菜單中顯示的內(nèi)容(側(cè)邊欄)则北。

<?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">

    <!--  主屏幕的內(nèi)容 -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        </android.support.v7.widget.Toolbar>

    </FrameLayout>

    <!-- 側(cè)邊欄的內(nèi)容 -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:text="我是側(cè)邊欄中的 TextView"
        android:textSize="30sp"
        android:background="@android:color/white"/>

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

注意:關(guān)于第二個(gè)子控件,layout_gravity這個(gè)屬性必須指定痕慢,因?yàn)槲覀冃枰嬖V DrawerLayout 滑動(dòng)菜單是在屏幕的左邊還是右邊尚揣,這里指定了 start,表示根據(jù)系統(tǒng)語(yǔ)言進(jìn)行判定掖举,如果系統(tǒng)語(yǔ)言是從左往右的快骗,比如英語(yǔ)、漢語(yǔ)塔次,滑動(dòng)菜單就是在左邊方篮,如果系統(tǒng)語(yǔ)言是從右往左的,比如阿拉伯語(yǔ)励负,滑動(dòng)菜單就是在右邊藕溅。

??這時(shí)候會(huì)有點(diǎn)問題,可能用戶不知道可以滑動(dòng)继榆,不知道有側(cè)邊欄這個(gè)東西巾表,Material Design 建議的做法是在 Toolbar 的左邊加入一個(gè)導(dǎo)航按鈕汁掠,點(diǎn)擊按鈕就將側(cè)邊欄展示出來(lái)。

        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        /*
            通過(guò) getSupportActionBar()方法獲取 ActionBar集币,雖然是 ActionBar考阱,
            但是其實(shí)具體實(shí)現(xiàn)是由 ToolBar 來(lái)實(shí)現(xiàn)的
         */
        ActionBar actionBar = getSupportActionBar();
        /*
            這里注意,其實(shí) ToolBar 最左側(cè)的導(dǎo)航按鈕就叫做 HomeAsUp 按鈕
            他默認(rèn)的是一個(gè)返回箭頭鞠苟,我們修改了他的樣式
         */
        if(actionBar != null){
            //讓導(dǎo)航按鈕顯示出來(lái)
            actionBar.setDisplayHomeAsUpEnabled(true);
            //設(shè)置導(dǎo)航按鈕圖標(biāo)
            actionBar.setHomeAsUpIndicator(R.mipmap.ic_launcher);
        }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.backup:
                Toast.makeText(this, "backUp", Toast.LENGTH_SHORT).show();
                break;
            case R.id.delete:
                Toast.makeText(this, "delete", Toast.LENGTH_SHORT).show();
                break;
            case R.id.settings:
                Toast.makeText(this, "settings", Toast.LENGTH_SHORT).show();
                break;
            case android.R.id.home:
                /*
                    注意:這里乞榨,HomeAsUp 按鈕的 id 永遠(yuǎn)都是 android.R.id.home
                 */
                drawerLayout.openDrawer(GravityCompat.START);
                break;
            default:
                break;
        }
        return true;
    }

DrawerLayout 使用總結(jié):

    1. DrawerLayout 是一個(gè)布局,并且允許放入兩個(gè)直接子控件偶妖,第一個(gè)控件是主屏幕中顯示的內(nèi)容姜凄,第二個(gè)控件是滑動(dòng)菜單中顯示的內(nèi)容。
    1. 第二個(gè)控件必須制定 layout_gravity 屬性趾访,用于告訴 DrawerLayout 是從哪個(gè)方向滑動(dòng)出來(lái)的态秧。

三、NavigationView

??NavigationView 是 Design Support 庫(kù)中提供的一個(gè)控件扼鞋,所以我們需要引入這個(gè)庫(kù)申鱼,而且在使用 NavigationView 之前,我們需要提前準(zhǔn)備好兩個(gè)東西:menu 和 headerLayout云头,menu 是用來(lái)在 NavigationView 中顯示具體的菜單項(xiàng)的捐友,headerLayout 則是用來(lái)在 NavigationView 中顯示頭布局的。

    //design 庫(kù)
    compile 'com.android.support:design:24.2.1'
    //circleimageview
    compile 'de.hdodenhof:circleimageview:2.1.0'

??CircleImageView 可以用來(lái)輕松實(shí)現(xiàn)圖片圓形化的功能溃槐,項(xiàng)目主頁(yè)地址是:https://github.com/hdodenhof/CircleImageView
??在開始使用 NavigationView 之前匣砖,我們還需要提前準(zhǔn)備好兩個(gè)東西:menu 和 headerLayout,其中 menu 是用來(lái)在 NavigationView 中顯示具體的菜單項(xiàng)的昏滴, headerLayout 則是用來(lái)在顯示頭部布局的猴鲫。
??接下來(lái)在 menu 文件夾中創(chuàng)建一個(gè) xml 文件,叫做nav_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- group表示一個(gè)組谣殊,checkableBehavior屬性指定為single表示組中所有菜單項(xiàng)只能單選 -->
    <group android:checkableBehavior="single">
        <item android:id="@+id/nav_call"
            android:icon="@mipmap/ic_launcher"
            android:title="Call" />

        <item android:id="@+id/nav_friends"
            android:icon="@mipmap/ic_launcher"
            android:title="Friends" />

        <item android:id="@+id/nav_location"
            android:icon="@mipmap/ic_launcher"
            android:title="Location" />

        <item android:id="@+id/nav_mail"
            android:icon="@mipmap/ic_launcher"
            android:title="Mail" />

        <item android:id="@+id/nav_task"
            android:icon="@mipmap/ic_launcher"
            android:title="Task" />
    </group>
</menu>

??然后我們?cè)?layout 文件夾中創(chuàng)建一個(gè) xml 文件拂共,命名為:nav_header.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 這里寬度設(shè)為match_parent姻几,高度設(shè)為180dp宜狐,這是一個(gè) NavigationView 比較合適的高度 -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:padding="10dp"
    android:background="?attr/colorPrimary"
    android:orientation="vertical">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/icon_img"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_centerInParent="true"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/mail"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="www.baidu.com@game.com"
        android:textColor="#ffffff"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/mail"
        android:text="Tony"
        android:textColor="#ffffff"
        android:textSize="14sp"/>

</RelativeLayout>

??然后修改 Activity 的 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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 主布局 -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        </android.support.v7.widget.Toolbar>

    </FrameLayout>

    <!-- 側(cè)邊欄 -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/nav_menu">
        <!-- 這里通過(guò) app:header 和 app:menu 屬性將我們剛才準(zhǔn)備好的
             menu 和 headerLayout 設(shè)置拉進(jìn)去 -->

    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>
        navView = (NavigationView) findViewById(R.id.nav_view);
        //設(shè)置默認(rèn)選中的菜單項(xiàng)
        navView.setCheckedItem(R.id.nav_call);
        //菜單項(xiàng)選中事件監(jiān)聽
        navView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                drawerLayout.closeDrawers();
                return true;
            }
        });
NavigationView.png

NavigationView使用總結(jié):

  • 1.使用 NavigationView 需要引入design 庫(kù)。
  • 2.還需要準(zhǔn)備兩個(gè) xml 文件:展示 menu 的 xml 文件蛇捌,和展示頭部 header 的 xml 文件抚恒。
  • 3.頭部的 header 的 xml 布局文件中,最外層根布局高度設(shè)置為180dp络拌,這是一個(gè)比較適合 NavigationView 的高度柑爸。
  • 4.然后通過(guò) app:menu 和 app:headerLayout屬性來(lái)指定文件。

四盒音、FloatingActionButton (懸浮按鈕)

??這是 Design Support 庫(kù)中提供的一個(gè)控件表鳍,默認(rèn)使用 colorAccent 來(lái)作為按鈕的顏色。

<?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">

    <!-- 主布局 -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        </android.support.v7.widget.Toolbar>

        <!-- 懸浮按鈕 -->
        <!-- 這里 end 和 start 一樣祥诽,如果系統(tǒng)語(yǔ)言是從左往右的譬圣,那么 end
             就在右邊,如果系統(tǒng)語(yǔ)言是從右往左的雄坪,那么 end 就在左邊厘熟。
             可以使用 app:elevation 屬性來(lái)給按鈕指定一個(gè)高度值,高度值
             越大维哈,投影范圍也越大绳姨,但是投影效果越淡,高度值越小阔挠,投影范圍
             也越小飘庄,投影效果越濃 -->
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/ic_launcher"
            app:elevation="8dp"/>

    </FrameLayout>

    <!-- 側(cè)邊欄 -->
    <!-- ...... -->

</android.support.v4.widget.DrawerLayout>
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(ThirdActivity.this, "點(diǎn)擊了懸浮按鈕", Toast.LENGTH_SHORT).show();
            }
        });

五、Snackbar

??還是由 Design Support 庫(kù)提供的购撼。但是需要明確一點(diǎn)跪削,Snackbar 并不是 Toast 的替代品,他們兩者之間有著不同的應(yīng)用場(chǎng)景迂求。Toast 的作用是告訴用戶現(xiàn)在發(fā)生了什么事情碾盐,用戶只能被動(dòng)接受。而 Snackbar 則在這方面進(jìn)行了擴(kuò)展揩局,它允許在提示當(dāng)中加入一個(gè)可交互按鈕毫玖,當(dāng)用戶點(diǎn)擊按鈕的時(shí)候可以執(zhí)行一些額外的操作邏輯。

        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                Toast.makeText(ThirdActivity.this, "點(diǎn)擊了懸浮按鈕", Toast.LENGTH_SHORT).show();
                //使用 Snackbar
                /*
                    Snackbar 使用 make 方法來(lái)創(chuàng)建
                        參1:傳入一個(gè) View 對(duì)象凌盯,只要是當(dāng)前界面任意一個(gè) View 都可以付枫,Snackbar 會(huì)使用
                             這個(gè) View 來(lái)自動(dòng)查找最外層的布局,用于展示Snackbar
                        參2:Snackbar 中顯示的內(nèi)容
                        參3:Snackbar 顯示的時(shí)長(zhǎng)
                 */
                Snackbar.make(v,"是你點(diǎn)擊了懸浮按鈕十气?",Snackbar.LENGTH_SHORT)
                        //通過(guò) setAction 方法設(shè)置一個(gè)動(dòng)作
                        .setAction("Yes", new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                Toast.makeText(ThirdActivity.this, "是我點(diǎn)擊了", Toast.LENGTH_SHORT).show();
                            }
                            //調(diào)用 show() 方法讓 Snackbar 顯示出來(lái)
                        }).show();
            }
        });
Snackbar.png

??不管是點(diǎn)擊 YES 還是過(guò)一段時(shí)間等待 Snackbar 自動(dòng)消失励背,Snackbar都是自帶動(dòng)畫效果的,但是你會(huì)發(fā)現(xiàn)一個(gè)問題砸西,就是 Snackbar 將我們的 FloatingActionBar 給擋住了叶眉,這就需要借助 CoordinatorLayout 就行了。

六芹枷、CoordinatorLayout

??CoordinatorLayout 可以說(shuō)是一個(gè)加強(qiáng)版的 FrameLayout衅疙,該布局也是由 Design Support 庫(kù)提供的,在普通情況下和 FrameLayout 基本一致鸳慈。
??事實(shí)上饱溢,CoordinatorLayout 可以監(jiān)聽其所有子控件的各種事件,然后自動(dòng)幫我們做出最為合理的響應(yīng)走芋,舉個(gè)例子:剛才彈出的 Snackbar 將懸浮按鈕擋住了绩郎,如果我們讓 CoordinatorLayout 監(jiān)聽到 Snackbar 的彈出事件潘鲫,那么它會(huì)自動(dòng)將內(nèi)部的 FloatingActionButton 向上偏移,從而確保不會(huì)被 Snackbar 擋住肋杖。

<?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">

    <!-- 主布局 -->
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        </android.support.v7.widget.Toolbar>

        <!-- 懸浮按鈕 -->
        <!-- 這里 end 和 start 一樣溉仑,如果系統(tǒng)語(yǔ)言是從左往右的,那么 end
             就在右邊状植,如果系統(tǒng)語(yǔ)言是從右往左的浊竟,那么 end 就在左邊。
             可以使用 app:elevation 屬性來(lái)給按鈕指定一個(gè)高度值津畸,高度值
             越大振定,投影范圍也越大,但是投影效果越淡肉拓,高度值越小后频,投影范圍
             也越小,投影效果越濃 -->
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/ic_launcher"
            app:elevation="8dp"/>

    </android.support.design.widget.CoordinatorLayout>

    <!-- 側(cè)邊欄 -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/nav_menu">

    </android.support.design.widget.NavigationView>

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

CoordinatorLayout.png

??問題解決了帝簇,但是有點(diǎn)奇怪徘郭,F(xiàn)loatingActionButton 是 CoordinatorLayout 的子控件沒問題,但 Snackbar 并不是丧肴,為什么 CoordinatorLayout 還會(huì)監(jiān)聽到呢残揉?

道理很簡(jiǎn)單,我們?cè)?Snackbar 的 make() 方法中傳入的第一個(gè)參數(shù)芋浮,就是用來(lái)指定 Snackbar 是基于哪個(gè) View 來(lái)觸發(fā)的抱环,我們傳入的是 FloatingActionBar,而 FloatingActionBar 又是 CoordinatorLayout 中的子控件纸巷,所以這個(gè)事件就能被監(jiān)聽到镇草,如果給 Snackbar 的 make() 方法的第一個(gè)參數(shù)傳入別的 View,比如傳入 DrawerLayout瘤旨,那么 Snackbar 就會(huì)再次遮擋懸浮按鈕梯啤,因?yàn)?DrawerLayout 不是 CoordinatorLayout 的子控件,CoordinatorLayout 也就無(wú)法堅(jiān)挺到 Snackbar 的彈出和隱藏事件了存哲。

FloatingActionBar因宇、Snackbar、CoordinatorLayout 使用總結(jié)

  • 1.這三個(gè)控件都是基于 Design Support 庫(kù)中的
  • 2.FloatingActionBar 可以通過(guò) android:src 屬性設(shè)置圖標(biāo)祟偷,還可以通過(guò) app:elevation 設(shè)置按鈕懸浮高度察滑,設(shè)置點(diǎn)擊事件和其他 View 的方法一樣
  • 3.CoordinatorLayout 其實(shí)就是高級(jí) FrameLayout,但是它可以監(jiān)聽其所有子控件的各種事件修肠,然后自動(dòng)做出最為合理的響應(yīng)贺辰。
  • 4.Snackbar 通過(guò) make 方法創(chuàng)建,通過(guò)setAction 方法設(shè)置一個(gè)動(dòng)作,可以和用戶進(jìn)行交互饲化,通過(guò) show 方法將 Snackbar 顯示出來(lái)莽鸭。
  • 5.Snackbar 的 make 方法中,參1可以是當(dāng)前布局的任意一個(gè) View吃靠,如果有 FloatingActionBar 最好傳入 FloatingActionBar蒋川,然后和 CoordiantorLayout 一起使用,避免 Snackbar 擋住 FloatingActionBar撩笆。
  • 6.FloatingActionBar 可以通過(guò) app:layout_anchor="@id/xxx" 屬性設(shè)置錨點(diǎn),指定懸浮按鈕出現(xiàn)在某個(gè)控件區(qū)域內(nèi)缸浦,然后使用 app:layout_anchorGravity 屬性將懸浮按鈕定位在區(qū)域內(nèi)的某個(gè)位置夕冲。

七、CardView(卡片式布局)

??CardView 由 appcompat-v7 提供裂逐,實(shí)際上 CardView 也是一個(gè) FrameLayout歹鱼,只是額外提供了圓角和陰影等效果,看上去會(huì)有立體的感覺卜高。
??我們使用一個(gè)簡(jiǎn)單的例子來(lái)展示一下 CardView 控件

<?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">

    <!-- 主布局 -->
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        </android.support.v7.widget.Toolbar>
        <!-- 這里添加一個(gè) RecyclerView -->
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

        </android.support.v7.widget.RecyclerView>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/ic_launcher"
            app:elevation="8dp"/>

    </android.support.design.widget.CoordinatorLayout>

    <!-- 側(cè)邊欄 -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header"
        app:menu="@menu/nav_menu">

    </android.support.design.widget.NavigationView>

</android.support.v4.widget.DrawerLayout>
/**
 * 實(shí)體類
 */

public class Fruit {

    private String name;//水果的名字
    private int imageId;//水果對(duì)應(yīng)資源的圖片id

    public Fruit(){

    }

    public Fruit(String name, int imageId) {
        this.name = name;
        this.imageId = imageId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getImageId() {
        return imageId;
    }

    public void setImageId(int imageId) {
        this.imageId = imageId;
    }

    @Override
    public String toString() {
        return "Fruit{" +
                "name='" + name + '\'' +
                ", imageId=" + imageId +
                '}';
    }
}
<!-- 這個(gè)是RecyclerView的item布局 -->
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    android:orientation="vertical"
    app:cardCornerRadius="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/iv_fruit"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:scaleType="centerCrop" />

        <TextView
            android:id="@+id/tv_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_margin="5dp"
            android:textSize="16sp" />

    </LinearLayout>

</android.support.v7.widget.CardView>
/**
 * RecyclerView 的適配器
 */
public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder>{

    private List<Fruit> mFruitList;
    private Context mContext;

    public FruitAdapter(List<Fruit> list){
        this.mFruitList = list;
    }

    static class ViewHolder extends RecyclerView.ViewHolder{

        ImageView ivFruit;
        TextView tvName;

        public ViewHolder(View itemView) {
            super(itemView);
            ivFruit = itemView.findViewById(R.id.iv_fruit);
            tvName = itemView.findViewById(R.id.tv_name);
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if(mContext == null){
            mContext = parent.getContext();
        }
        View view = LayoutInflater.from(mContext).inflate(R.layout.fruit_item,parent,false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.tvName.setText(fruit.getName());
        Glide.with(mContext).load(fruit.getImageId()).into(holder.ivFruit);
    }

    @Override
    public int getItemCount() {
        return mFruitList == null ? 0 : mFruitList.size();
    }
}

這里使用了 Glide 加載圖片弥姻,Glide 項(xiàng)目主頁(yè)地址是:https://github.com/bumptech/glide
這里為什么要用 Glide 而不用傳統(tǒng)的方式設(shè)置圖片呢?因?yàn)槿绻麍D片像素非常高的話掺涛,如果不進(jìn)行壓縮就直接展示庭敦,很容易就會(huì)引起內(nèi)存泄露,而 Glide 在內(nèi)部做了許多復(fù)雜的邏輯操作薪缆,其中就包括了圖片的壓縮秧廉。

    //數(shù)據(jù)
    private Fruit[] fruits = {
            new Fruit("Apple", R.mipmap.ic_launcher),
            new Fruit("Banana", R.mipmap.ic_launcher),
            new Fruit("Orange", R.mipmap.ic_launcher),
            new Fruit("Watermelon", R.mipmap.ic_launcher),
            new Fruit("Pear", R.mipmap.ic_launcher),
            new Fruit("Grape", R.mipmap.ic_launcher),
            new Fruit("Pineapple", R.mipmap.ic_launcher),
            new Fruit("Strawbeery", R.mipmap.ic_launcher),
            new Fruit("Cherry", R.mipmap.ic_launcher),
            new Fruit("Mango", R.mipmap.ic_launcher)
    };
    private List<Fruit> fruitList = new ArrayList<>();
        initFruits();

        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(this,2);
        recyclerView.setLayoutManager(gridLayoutManager);
        FruitAdapter adapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(adapter);
    private void initFruits() {
        fruitList.clear();
        for (int i = 0; i < 50; i++) {
            Random random = new Random();
            int index = random.nextInt(fruits.length);
            fruitList.add(fruits[index]);
        }
    }
CardView.png

??CardView 的效果已經(jīng)出來(lái)了,但是你自己觀察一下拣帽,ToolBar 被 RecyclerView 擋住了疼电,怎么辦?這就要借助另一個(gè)工具 -- AppBarLayout了减拭。

八蔽豺、AppBarLayout

??分析下上述問題的原因,因?yàn)?ToolBar 和 RecyclerView 都放在 CoordinatorLayout 中拧粪,而 CoordinatorLayout 是一個(gè)加強(qiáng)版的 FrameLayout修陡,那么肯定會(huì)遮擋了啊。那么如果我們?cè)?CoordinatorLayout 內(nèi)既们,給 ToolBar 和 RecyclerView 的包一層 LinearLayout 或者 RelativeLayout 是不是就可以了呢濒析?是的,是可以了啥纸,但是号杏,我們既然引出了 AppBarLayout,就有用 AppBarLayout 的理由。
??AppBarLayout 實(shí)際上是一個(gè)垂直方向上的 LinearLayout盾致,而且它也是 Design Support 庫(kù)中的空間主经,它在其內(nèi)部做了非常多的滾動(dòng)事件的封裝。先看看如何使用:

    <!-- 主布局 -->
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- 在 Toolbar 外層嵌套一個(gè) AppBarLayout -->
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            </android.support.v7.widget.Toolbar>

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

        <!-- 給 ReccylerView 添加一個(gè) app:layout_behavior 屬性庭惜,值也是固定這么寫的 -->
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

        </android.support.v7.widget.RecyclerView>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/ic_launcher"
            app:elevation="8dp" />

    </android.support.design.widget.CoordinatorLayout>
AppBarLayout1.png

注意:這里如果將 RecyclerView 也放在 AppBarLayout 中罩驻,則會(huì)無(wú)法滑動(dòng)。如果不給 RecyclerView 添加 app:layout_behavior 屬性护赊,則會(huì)出現(xiàn) RecyclerView 的上面部分被 ToolBar 遮蓋了惠遏,如下圖所示。

AppBarLayout2.png

??注意頂部骏啰,這個(gè)是 RecyclerView 滑動(dòng)到頂部的樣子节吮,也就是說(shuō) RecyclerView 的上面部分被 ToolBar 遮蓋了。
??當(dāng) AppBarLayout 接收到滾動(dòng)事件的時(shí)候判耕,它內(nèi)部的子控件其實(shí)是可以指定如何去響應(yīng)這些事件的透绩,通過(guò)app:layout_scrollFlags屬性就可以

    <!-- 主布局 -->
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- 在 Toolbar 外層嵌套一個(gè) AppBarLayout -->
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <!-- 給 Toolbar 添加了 app:layout_scrollFlags 屬性
                 其中 scroll 表示當(dāng) RecyclerView 向上滾動(dòng)的時(shí)候,Toolbar 會(huì)跟隨一起向上滾動(dòng)并實(shí)現(xiàn)隱藏;
                 enterAlways 表示當(dāng)RecyclerView 向下滾動(dòng)的時(shí)候壁熄,Toolbar 會(huì)跟著一起向下滾動(dòng)并重新顯示;
                 snap 表示當(dāng) Toolbar 還沒有完全隱藏或顯示的時(shí)候帚豪,會(huì)根據(jù)當(dāng)前滾動(dòng)的距離,自動(dòng)選擇是隱藏還是顯示-->
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_scrollFlags="scroll|enterAlways|snap">

            </android.support.v7.widget.Toolbar>

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

        <!-- 給 RecyclerView 添加一個(gè) app:layout_behavior 屬性草丧,值也是固定這么寫的 -->
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

        </android.support.v7.widget.RecyclerView>

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/ic_launcher"
            app:elevation="8dp" />

    </android.support.design.widget.CoordinatorLayout>

CardView狸臣、AppBarLayout使用總結(jié):

  • 1.CardView 是由 appcompat-v7 庫(kù)提供,實(shí)質(zhì)上是一個(gè) FrameLayout方仿。AppBarLayout是由 Design Support 庫(kù)提供固棚,實(shí)質(zhì)上是一個(gè)垂直方向上的 LinearLayout.
  • 2.CardView 中使用 app:cardCornerRadius 屬性指定卡片圓角的弧度,數(shù)值越大仙蚜,圓角的弧度也越大此洲,還可以使用 app:elevation 屬性指定卡片的高度,高度值越大委粉,投影范圍越大呜师,但是投影效果越淡。高度值越小贾节,投影范圍也越小汁汗,但是投影效果越濃。
  • 3.解決 RecyclerView 覆蓋 Toolbar 問題栗涂,只需要兩步:第一步 --- 將 Toolbar 嵌套在 AppBarLayout 中知牌;第二步 --- 給RecyclerView 指定一個(gè)布局行為:app:layout_behavior="@string/appbar_scrolling_view_behavior"
  • 4.讓 Toolbar 跟隨 RecyclerView 一起滑動(dòng)的效果:給 Toolbar 設(shè)置屬性app:layout_scrollFlags="scroll|enterAlways|snap"
    其中,scroll 表示 RecyclerView 上滑時(shí)斤程,Toolbar 會(huì)隱藏角寸;enterAlways 表示 RecyclerView 下滑時(shí),Toolbar 會(huì)顯示;snap 表示 Toolbar 沒有完全隱藏或顯示的時(shí)候扁藕,會(huì)根據(jù)當(dāng)前滑動(dòng)的距離沮峡,自動(dòng)選擇隱藏還是顯示。

九亿柑、SwipeRefreshLayout(下拉刷新)

??SwipeRefreshLayout 是由 support-v4 庫(kù)提供邢疙,一般下拉刷新都配合 RecyclerView 一起使用,我們只需要在 RecyclerView 外層嵌套一個(gè) SwipeRefreshLayout 即可望薄。

    <!-- 主布局 -->
    <android.support.design.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- 在 Toolbar 外層嵌套一個(gè) AppBarLayout -->
        <android.support.design.widget.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                app:layout_scrollFlags="scroll|enterAlways|snap"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            </android.support.v7.widget.Toolbar>

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

        <android.support.v4.widget.SwipeRefreshLayout
            android:id="@+id/swipe_refresh"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recycler_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

            </android.support.v7.widget.RecyclerView>

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

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@mipmap/ic_launcher"
            app:elevation="8dp" />

    </android.support.design.widget.CoordinatorLayout>

注意:這里因?yàn)?RecyclerView 外面嵌套了一層 SwipeRefreshLayout 所以疟游,之前設(shè)置的 app:layout_behavior 屬性也必須要放到 SwipeRefreshLayout 中才行。

        swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
        //設(shè)置下拉刷新進(jìn)度條的顏色痕支,參數(shù)是可變參數(shù)
        swipeRefresh.setColorSchemeResources(R.color.colorPrimary,R.color.colorAccent);
        //設(shè)置下拉刷新的監(jiān)聽器乡摹,當(dāng)觸發(fā)了下拉刷新操作時(shí),就會(huì)回調(diào)這個(gè)監(jiān)聽器的 onRefresh 方法
        swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshFruits();
            }
        });
    private void refreshFruits(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        initFruits();
                        adapter.notifyDataSetChanged();
                        //傳入 false采转,表示刷新事件結(jié)束,并隱藏刷新進(jìn)度條
                        swipeRefresh.setRefreshing(false);
                    }
                });
            }
        }).start();
    }
swipeRefreshLayout.png

十瞬痘、可折疊式標(biāo)題欄

??如果我們希望根據(jù)自己的喜好隨意定制標(biāo)題欄的樣式故慈,比如實(shí)現(xiàn)一個(gè)可折疊式的標(biāo)題欄的效果,就需要借助 CollapsingToolbarLayout 這個(gè)工具框全。
??CollapsingToolbarLayout 是一個(gè)作用于 Toolbar 基礎(chǔ)之上的布局察绷,它也是由 Design Support 庫(kù)提供,CollapsingToolbarLayout 可以讓 Toolbar 的效果變得更加豐富津辩。

注意:CollapsingToolbarLayout 不能獨(dú)立存在拆撼,它在設(shè)計(jì)的時(shí)候就被限定只能作為AppBarLayout 的直接子布局來(lái)使用,而AppBarLayout 又必須是 CoordinatorLayout 的子布局喘沿,所以嵌套的代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="250dp">

        <!-- 嵌套在 AppBarLayout 中的 CollapsingToolbarLayout
              app:contentScrim 屬性用于指定 CollapsingToolbarLayout 在趨于折疊狀態(tài)
              以及折疊之后的背景色闸度,其實(shí) CollapsingToolbarLayout 在折疊后就是一個(gè)普
              通的Toolbar。
              app:layout_scrollFlags 屬性中 scroll 表示 CollapsingToolbarLayout 會(huì)
              隨著內(nèi)容詳情的滾動(dòng)一起滾動(dòng)蚜印,exitUntilCollapsed 表示當(dāng) CollapsingToolbarLayout
              會(huì)隨著完成折疊之后就保留在界面上莺禁,不再移出屏幕-->
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <!-- app:layout_collapseMode 屬性指定當(dāng)前控件在 CollapsingToolbarLayout
              折疊過(guò)程中的折疊模式,pin 表示在折疊過(guò)程中位置始終保持不變窄赋,parallax 表示
              會(huì)在折疊的過(guò)程中產(chǎn)生一定的錯(cuò)位偏移哟冬,視覺效果很好 -->
            <ImageView
                android:id="@+id/iv_fruit"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                app:layout_collapseMode="parallax"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin">

            </android.support.v7.widget.Toolbar>

        </android.support.design.widget.CollapsingToolbarLayout>

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

    <!-- NestedScrollView 是在 ScrollView 的基礎(chǔ)之上增加了嵌套
         響應(yīng)滾動(dòng)事件的功能,由于 CoordinatorLayout 本身已經(jīng)可以
         響應(yīng)滾動(dòng)事件了忆绰,因此我們?cè)趦?nèi)部就需要使用 NestedScrollView
         或 RecyclerView 浩峡,而且還加了 app:layout_behavior 屬性,
         為了不要遮擋Toolbar -->
    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="15dp"
                android:layout_marginLeft="15dp"
                android:layout_marginRight="15dp"
                android:layout_marginTop="35dp"
                app:cardCornerRadius="4dp">

                <TextView
                    android:id="@+id/tv_fruit_content"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_margin="10dp" />

            </android.support.v7.widget.CardView>

        </LinearLayout>

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

    <!-- 使用 app:layout_anchor 屬性指定一個(gè)錨點(diǎn)
         使用 app:layout_anchorGravity 屬性將懸浮按鈕定位在標(biāo)題欄區(qū)域的右下角 -->
    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|end"/>

</android.support.design.widget.CoordinatorLayout>

該布局分三部分错敢,最外層是一個(gè) CoordinatorLayout
第一部分:在 CoordinatorLayout 內(nèi)嵌一個(gè) AppBarLayout翰灾,然后在 AppBarLayout 中再內(nèi)嵌一個(gè) CollapsingToolbarLayout劲腿,然后再 CollapsingToolbarLayout 中再加上 ImageView 和 Toolbar 兩個(gè)控件甘凭。
第二部分:加入 NestedScrollView 控件,和 AppBarLayout 是同級(jí)的,在 NestedScrollView 內(nèi)部嵌套一個(gè) LinearLayout触趴,然后在 LinearLayout 中加上 CardView 布局。
第三部分:比較簡(jiǎn)單拼窥,就是加一個(gè)FloatingActionButton抛人,和 AppBarLayout 以及 NestedScrollView 都是同級(jí)的。

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
        collapsingToolbar.setTitle("Apple");

        ImageView ivFruit = (ImageView) findViewById(R.id.iv_fruit);
        TextView tvFruitContent = (TextView) findViewById(R.id.tv_fruit_content);
        Glide.with(this).load(R.mipmap.ic_launcher).into(ivFruit);
        tvFruitContent.setText(generateFruitContent("Apple"));
    /**
     * 生成比較長(zhǎng)的內(nèi)容
     */
    private String generateFruitContent(String name) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 500; i++) {
            sb.append(name);
        }
        return sb.toString();
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case android.R.id.home:
                finish();
                return true;
            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }
device-2018-04-17-150418.png

CollapsingToolbarLayout使用總結(jié):

  • 1.CollapsingToolbarLayout 是不能獨(dú)立存在的糜芳,必須作為 AppBarLayout 的直接子布局來(lái)使用飒货,AppBarLayout 又必須是 CoordinatorLayout 的子布局。
  • 2.通過(guò)設(shè)置 app:contentScrim 屬性用于指定 CollapsingToolbarLayout 在趨于折疊狀態(tài)和折疊之后的背景色峭竣。還有 app:layout_scrollFlags 屬性塘辅,scroll 表示 CollapsingToolbarLayout 會(huì)隨之一起滾動(dòng),exitUntilCollapsed 表示當(dāng) CollapsingToolbarLayout 隨著滾動(dòng)完成折疊之后就保留在界面上皆撩,不再移出屏幕扣墩。
  • 3.CollapsingToolbarLayout 的子控件,可以添加 app:layout_collapseMode 屬性指定當(dāng)前控件在 CollapsingToolbarLayout 折疊過(guò)程中的折疊模式扛吞,pin 表示在折疊的過(guò)程中位置始終保持不變呻惕,parallax 表示會(huì)在折疊的過(guò)程中產(chǎn)生一定的錯(cuò)位偏移。

十一滥比、系統(tǒng)狀態(tài)欄

??在 Android 5.0 系統(tǒng)之前亚脆,我們是無(wú)法對(duì)狀態(tài)欄的背景或顏色進(jìn)行操作的。

??想讓背景圖能夠和系統(tǒng)狀態(tài)欄融合盲泛,需要借助 android:fitsSystemWindows 這個(gè)屬性濒持,在控件中,將該屬性指定為 true寺滚,表示該控件會(huì)出現(xiàn)在系統(tǒng)狀態(tài)欄里柑营,修改布局文件:


image.png

這里如果只給 ImageView 設(shè)置 android:fitsSystemWindows 屬性是沒有用的,必須將 ImageView 布局結(jié)構(gòu)中的所有父布局都設(shè)置上這個(gè)屬性才可以村视。

image.png

??有點(diǎn)變化由境,但不是我們要的效果。這時(shí)就需要將狀態(tài)欄顏色指定成透明色才行蓖议。

設(shè)置成透明的方法很簡(jiǎn)單虏杰,在主題中將 android:statusBarColor 屬性的值指定成 @android:color/transparent 就可以了,但是問題是勒虾,android:statusBarColor 這個(gè)屬性是從 API 21(Android 5.0)開始才有的纺阔,之前的系統(tǒng)無(wú)法指定這個(gè)屬性。

??為了解決上述問題修然,我們做如下操作


image.png

??然后在 values-v21 目錄下創(chuàng)建一個(gè)styles.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="FruitActivityTheme" parent="AppTheme">
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

由于 values-v21 目錄是只有 Android 5.0 及其以上的系統(tǒng)才會(huì)去讀取的笛钝,所以质况,這么寫是沒問題的。但是 Android 5.0 之前的系統(tǒng)卻無(wú)法識(shí)別 FruitActivityTheme 這個(gè)主題玻靡,因此我們還需要修改 values/styles.xml 文件结榄。

    <!-- 因?yàn)锳ndroid 5.0 之前的系統(tǒng)無(wú)法指定狀態(tài)欄的顏色,所以這里什么都不用做 -->
    <style name="FruitActivityTheme" parent="AppTheme">

    </style>

??最后別忘了在清單文件中給 Activity 添加 Theme 屬性


image.png

最后囤捻,Material Design 的官方文章:https://material.google.com

下一篇文章:http://www.reibang.com/p/501825ee6fff

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末臼朗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蝎土,更是在濱河造成了極大的恐慌视哑,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件誊涯,死亡現(xiàn)場(chǎng)離奇詭異挡毅,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)暴构,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門跪呈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人取逾,你說(shuō)我怎么就攤上這事庆械。” “怎么了菌赖?”我有些...
    開封第一講書人閱讀 156,723評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)沐序。 經(jīng)常有香客問我琉用,道長(zhǎng),這世上最難降的妖魔是什么策幼? 我笑而不...
    開封第一講書人閱讀 56,357評(píng)論 1 283
  • 正文 為了忘掉前任邑时,我火速辦了婚禮,結(jié)果婚禮上特姐,老公的妹妹穿的比我還像新娘晶丘。我一直安慰自己,他們只是感情好唐含,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評(píng)論 5 384
  • 文/花漫 我一把揭開白布浅浮。 她就那樣靜靜地躺著,像睡著了一般捷枯。 火紅的嫁衣襯著肌膚如雪滚秩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評(píng)論 1 289
  • 那天淮捆,我揣著相機(jī)與錄音郁油,去河邊找鬼本股。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桐腌,可吹牛的內(nèi)容都是我干的拄显。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼案站,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼躬审!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起嚼吞,我...
    開封第一講書人閱讀 37,672評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盒件,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后舱禽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炒刁,經(jīng)...
    沈念sama閱讀 44,118評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評(píng)論 2 325
  • 正文 我和宋清朗相戀三年誊稚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了翔始。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,599評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡里伯,死狀恐怖城瞎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疾瓮,我是刑警寧澤脖镀,帶...
    沈念sama閱讀 34,264評(píng)論 4 328
  • 正文 年R本政府宣布,位于F島的核電站狼电,受9級(jí)特大地震影響蜒灰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜肩碟,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評(píng)論 3 312
  • 文/蒙蒙 一强窖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧削祈,春花似錦翅溺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吨拍,卻和暖如春叙凡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背密末。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工握爷, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留跛璧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評(píng)論 2 360
  • 正文 我出身青樓新啼,卻偏偏與公主長(zhǎng)得像追城,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子燥撞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評(píng)論 2 348

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

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,737評(píng)論 25 707
  • 本篇文章主要介紹以下幾個(gè)知識(shí)點(diǎn):Toolbar滑動(dòng)菜單懸浮按鈕卡片式布局下拉刷新可折疊式標(biāo)題欄 Material ...
    開心wonderful閱讀 2,407評(píng)論 2 48
  • MaterialDesign是一套全新的界面設(shè)計(jì)語(yǔ)言,包含視覺,運(yùn)動(dòng),互動(dòng)效果等特性. Design Suppor...
    小徐andorid閱讀 947評(píng)論 0 9
  • CoordinatorLayout與滾動(dòng)的處理 CoordinatorLayout實(shí)現(xiàn)了多種Material De...
    cxm11閱讀 6,570評(píng)論 1 15
  • 1 我的大學(xué)生活之大學(xué)英語(yǔ)學(xué)習(xí) 1) 在這個(gè)學(xué)期的大學(xué)英語(yǔ)學(xué)習(xí)中座柱,我的GPS [Gains] 1.收獲了一個(gè)語(yǔ)伴...
    1701段景昱閱讀 170評(píng)論 5 3