前言:

继Android 6.0新控件(一),这里将介绍一下NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout的使用.文章都是自己学习过程中的记录,难免会有失误,还望大家不吝指出,谢谢.这里是Android 6.0新控件(一)FloatingActionButton,TextInputLayout,Snackbar,TabLayout的使用,

下面继续NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout控件的使用.

使用:

因为使用的是Support库中提供的新控件,所以当你使用这些控件中的任意一个时,都需要添加依赖.在build.gradle(moudle:app)中添加依赖:compile ‘com.android.support:design:24.2.1’ 版本号可自己匹配.

NavigationView

  • 简介:
    在Material Design中,Navigation drawer导航抽屉,被设计用于应用导航,提供了一种通用导航方式,体现了设计的一致性.而NavigationView的出现就是为了配合DrawerLayout的使用,作为Drawer的一部分,即导航菜单.NavigationView是一个导航菜单框架,使用menu资源填充数据是我们可以更简单高效的实现导航菜单.它提供了一些默认样式,选中项高亮,分组单选,分组子标题,以及可选的header.好了,说了这么说,不如几行代码来的直接…
  • 具体使用:
  • 布局文件:
<?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/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.listenergao.mytest.activity.NavigationViewActivity">
    <!--content-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

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

        <FrameLayout
            android:id="@+id/fl_content"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1">
        </FrameLayout>
    </LinearLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation"
        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.design.widget.NavigationView>


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

这里需要注意NavigationView的两个属性:app:headerLayout=”“和app:menu=”“,

app:headerLayout:接收一个layout布局,作为导航菜单顶部的Header.

app:menu:接收一个menu,作为导航菜单的菜单项,这个属性几乎是必选项,不然这个控件就是去意义了.不过也可以在运行时动态改变menu属性.

该布局的最外层容器是DrawerLayout,这里注意下android:fitsSystemWindows属性,这个属性的作用是根据系统的窗口调整布局,如系统的状态栏.(这里不细说)LinearLayout里面摆放了界面要显示的内容,其中使用include引入的布局是Toolbar,和FrameLayout.最后就是用于展示侧拉菜单中的菜单内容NavigationView,它的两个重要属性上面已经介绍了,这里就不罗嗦了.

这里是NavigationView添加的头布局内容和使用menu填充的菜单内容.

**//添加的头布局drawer_header.xml**
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="172dp"
    android:background="@drawable/drawer_background"
    android:paddingTop="25dp">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/civ_head"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_margin="16dp"
        android:elevation="4dp"
        android:src="@drawable/hacker"
        app:civ_border_color="@color/white"
        app:civ_border_width="2dp" />

    <TextView
        android:id="@+id/tv_username"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/tv_email"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
        android:textColor="@color/white" />

    <TextView
        android:id="@+id/tv_email"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="16dp"
        android:layout_marginLeft="16dp"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:textColor="@color/white" />


</RelativeLayout>


**//drawer_menu.xml**
<?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:icon="@drawable/ic_home_black"
            android:title="@string/home" />

        <item
            android:id="@+id/drawer_favourite"
            android:icon="@drawable/ic_favorite_black"
            android:title="@string/favourite" />

        <item
            android:id="@+id/drawer_download"
            android:icon="@drawable/ic_file_download_black"
            android:title="@string/download" />

        <item
            android:id="@+id/sub"
            android:title="subTitle">
            <menu>
                <item
                    android:id="@+id/drawer_more"
                    android:icon="@drawable/ic_more_horiz_black"
                    android:title="@string/more" />
                <item
                    android:id="@+id/drawer_settings"
                    android:icon="@drawable/ic_settings_black"
                    android:title="@string/settings" />
            </menu>
        </item>
    </group>

</menu>
  • Activity文件
public class NavigationViewActivity extends BaseActivity {

    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.drawerLayout)
    DrawerLayout drawerLayout;
    @BindView(R.id.navigation)
    NavigationView navigationView;

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_navigation_view;
    }

    @Override
    protected void initView() {
        ButterKnife.bind(this);

        //设置状态栏为全透明。
        StatusBarUtil.setTransparent(this);

        toolbar.setTitle("NavigationView");
        setSupportActionBar(toolbar);
        //设置DrawerLayout
        ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open, R.string.close) {
        };
        drawerToggle.syncState();
        drawerLayout.setDrawerListener(drawerToggle);
        //获取头布局内部的控件.在旧版本中,假如你要获得 NavigationView 中的文本控件,你可以在 activity 中直接调用 findViewById() 方法来获得。
        // 但是在 Support Library 23.1.0 版本之后,这个不再适用,在我使用的 Support Library 23.1.1 版本中,
        // 可以直接调用 getHeaderView()方法先得到 Header,然后在通过header来获得头部内的控件。
        View header = navigationView.getHeaderView(0);
        TextView userName = (TextView) header.findViewById(R.id.tv_username);
        TextView email = (TextView) header.findViewById(R.id.tv_email);
        userName.setText("Listener Gao");
        email.setText("hnthgys@gmail.com");

        //处理菜单列表种图标不显示原始颜色的问题.  当你设置完图标后,会发现无论图标的原始颜色是什么,都会全部变成灰色.
        // 此时,你可以通过app:itemIconTint="@color/..."属性为图标设置统一的颜色.当然,如果你需要图标显示自己原始的颜色,
        // 可以调用NavigationView的setItemIconTintList(ColorStateList tint)方法,参数传为null即可.
        //navigationView.setItemIconTintList(null);

        //设置菜单列表的点击事件。
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.drawer_home:
                        Toast.makeText(NavigationViewActivity.this, "Home", Toast.LENGTH_SHORT).show();
                        drawerLayout.closeDrawers();    //点击条目后,关闭侧滑才菜单
                        item.setChecked(true);          //设置点击过的item为选中状态,字体和图片的颜色会发生变化,颜色会变为和Toolbar的颜色一致。
                        toolbar.setTitle("Home");       //修改Toolbar显示的Title
                        break;
                    case R.id.drawer_favourite:
                        Toast.makeText(NavigationViewActivity.this, "Favourite", Toast.LENGTH_SHORT).show();
                        drawerLayout.closeDrawers();
                        item.setChecked(true);
                        toolbar.setTitle("Favourite");
                        break;
                    case R.id.drawer_download:
                        Toast.makeText(NavigationViewActivity.this, "Download", Toast.LENGTH_SHORT).show();
                        drawerLayout.closeDrawers();
                        item.setChecked(true);
                        toolbar.setTitle("Download");
                        break;
                    case R.id.drawer_more:
                        Toast.makeText(NavigationViewActivity.this, "More", Toast.LENGTH_SHORT).show();
                        drawerLayout.closeDrawers();
                        item.setChecked(true);
                        toolbar.setTitle("More");
                        break;
                    case R.id.drawer_settings:
                        Toast.makeText(NavigationViewActivity.this, "Settings", Toast.LENGTH_SHORT).show();
                        drawerLayout.closeDrawers();
                        item.setChecked(true);
                        toolbar.setTitle("Settings");
                        break;
                }
                return false;
            }
        });
    }

    @Override
    protected void initData() {

    }

    @Override
    public void onBackPressed() {
        //重写返回键,当侧滑菜单处于打开状态,点击返回键就关闭侧滑菜单。
        if (drawerLayout.isDrawerOpen(GravityCompat.START))
            drawerLayout.closeDrawers();
        else
            super.onBackPressed();
    }
}

代码中的注视已经很详细了,这里说一下就是当打开侧滑菜单时,设置状态栏的颜色,我这里是使用了StatusBarUtil将状态栏设置成了透明的(可以直接在github上直接搜到),再一个就是当打开侧滑菜单时,点击返回键,直接就把当前的Activity关闭了,这里是重写了返回键,判断侧滑菜单是否处于打开状态,如果处于打开状态就关闭侧滑菜单.

  • 效果图:

CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout

这三个控件之间存在着一定的关系,这里就放在一起介绍了.

  • 一,首先是CoordinatorLayout: CoordinatorLayout是一个超强的FrameLayout.CoordinatorLayout旨在用于两个基本用例:
  • 1,作为顶级应用程序的装饰或镀布局.(作为顶层布局)
  • 2,作为一个或多个子视图的特异性相互作用的容器.(调度协调子布局)

CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果.CoordinatorLayout通过设置子View的Behaviors来调度子View.系统(v7包)提供了AppBarLayout.Behavior,AppBarLayout.ScrollingViewBehavior,FloatingActionButton.Behavior,SwipDismissBehavior等.CoordinatorLayout是怎么协调子控件呢?其实说简单点:CoordinatorLayout主要用于协调内部的各个子控件进行交互,通过设置子控件的behavior来操控子控件的一些操作和动画。

  • 二,然后是AppBarLayout: AppBarLayout继承自LinearLayout,布局方向为垂直方向.AppBarLayout是在LinearLayout上加了一些材料设计的概念,它可以让你定制当某个可滚动View的滚动手势发生变化时,其内部的子View实现何种动作.一般情况下我们会在AppBarLayout中包裹Toolbar或者TabLayout,当滑动是可以选择需要隐藏的部分。AppBarLayout中有一个内置的Behavior类,而Toolbar和TabLayout中没有,由此可以看出正是因为AppBarLayout中又Behavior类,才能与CoordinatorLayout产生交互(AppBarLayout必须是CoordinatorLayout的直接子View)。需要注意的是AppBarLayout的子控件需要设置app:layout_scrollFlags属性(或者通过setScrollFlags()方法)才能达到其滑动效果。layout_scrollFlags属性有以下几种:
  • 1,scroll:设置该flag,该控件可以滑动到屏幕之外,若未设置则会固定在屏幕的顶部。
  • 2,enterAlways:设置该flag,向下任意的滑动都会导致该控件(设置layout_scrollFlags=”enterAlways”属性的控件)变为可见,启用快速“返回模式”。
  • 3,enterUntilCollapsed:向上滚动时收缩View,但可以固定Toolbar一直在上面。
  • 4,enterAlwaysCollapsed:当你的View已经设置minHeight属性又使用此标志时,你的View只能以最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。
  • 5,snap(v23.1):简单理解就是View有一种吸附效果,View不会存在局部显示的效果,要么全部滑动出屏幕,要么会在屏幕中显示,有点类似于ViewPager的左右滑动。

关于Lsyout_ScrollFlags属性的详细解释可以看这篇文章,解释的很详细。http://codecloud.net/17998.html

  • 三,最后是CollapsingToolbarLayout: CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承至FrameLayout,给它设置layout_scrollFlags,它可以控制包含在CollapsingToolbarLayout中的控件(如:ImageView、Toolbar)在响应layout_behavior事件时作出相应的scrollFlags滚动事件(移除屏幕或固定在屏幕顶端)。CollapsingToolbarLayout可以通过app:contentScrim设置折叠时工具栏布局的颜色,通过app:statusBarScrim设置折叠时状态栏的颜色。默认contentScrim是colorPrimary的色值,statusBarScrim是colorPrimaryDark的色值。CollapsingToolbarLayout的子布局有3种折叠模式(Toolbar中设置的app:layout_collapseMode):
  • 1,none:这个是默认属性,布局将正常显示,没有折叠的行为。
  • 2,pin: CollapsingToolbarLayout折叠后,Toolbar布局将固定在顶部。
  • 3,parallax: CollapsingToolbarLayout折叠时,此布局会有折叠视差效果。

当CollapsingToolbarLayout的子布局设置了parallax模式时,我们还可以通过app:layout_collapseParallaxMultiplier设置视差滚动因子,值为:0~1。

以上三种布局需要结合使用,并设置相应的属性才能达到很好的效果。下面是我写的两个效果:

  • 效果一:向上滑动隐藏App bar,因为这里设置了app:layout_scrollFlags=”scroll|enterAlways”,所以当向下滑动时会立即显示App bar。
  • 布局文件:这里需要注意的是需要使用Toolbar,对Toolbar不熟悉的可以参考这篇文章:Toolbar使用详解
<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <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="@color/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

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


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

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

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


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

这里使用了NestedScrollView控件,因为只有能支持滑动的控件才会有这种效果。还有就是设置的app:layout_behavior=”@string/appbar_scrolling_view_behavior”属性,可以看下上面的解释。

源码:
https://github.com/ListenerGao/MyTest/blob/master/app/src/main/java/com/listenergao/mytest/activity/AppBarLayoutActivity.java

  • 效果二:在CollapsingToolbarLayout中设置了一个ImageView和一个Toolbar。并把这个CollapsingToolbarLayout放到AppBarLayout中作为一个整体,并添加FloatActionButton。
  • 布局:
<?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:id="@+id/activity_collapsing_toolbar_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.listenergao.mytest.activity.CollapsingToolbarLayoutActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsing_toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginEnd="30dp"
            app:expandedTitleMarginStart="40dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:src="@drawable/hacker"
                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"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
        </android.support.design.widget.CollapsingToolbarLayout>

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

    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />

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

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="20dp"
        app:backgroundTint="@color/colorPrimary"
        android:src="@drawable/ic_favorite"
        app:elevation="4dp"
        app:fabSize="normal"
        app:layout_anchor="@id/app_bar_layout"
        app:layout_anchorGravity="bottom|right"
        app:pressedTranslationZ="8dp"
        app:rippleColor="@color/colorPrimaryDark"
        app:useCompatPadding="false" />


</android.support.design.widget.CoordinatorLayout>
  • 代码:
package com.listenergao.mytest.activity;

public class CollapsingToolbarLayoutActivity extends BaseActivity {

    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.activity_collapsing_toolbar_layout)
    CoordinatorLayout activityCollapsingToolbarLayout;
    @BindView(R.id.tv_content)
    TextView tvContent;
    @BindView(R.id.collapsing_toolbar_layout)
    CollapsingToolbarLayout collapsingToolbarLayout;
    @BindView(R.id.app_bar_layout)
    AppBarLayout appBarLayout;
    @BindView(R.id.fab)
    FloatingActionButton fab;

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_collapsing_toolbar_layout;
    }

    @Override
    protected void initView() {
        ButterKnife.bind(this);

        //设置状态栏为全透明。(这里使用了一个三方库,将状态栏设置为透明)
        StatusBarUtil.setTransparent(this);

//        toolbar.setTitle("CollapsingToolbarLayout");
        setSupportActionBar(toolbar);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        collapsingToolbarLayout.setTitle("CollapsingToolbarLayout");
        collapsingToolbarLayout.setExpandedTitleColor(Color.BLACK);     //设置展开时Title的颜色
        collapsingToolbarLayout.setCollapsedTitleTextColor(Color.WHITE);    //设置收缩时Title的颜色

        tvContent.setText("文字内容就省略了。。。");


    }

    @Override
    protected void initData() {

    }

    @OnClick(R.id.fab)
    public void onClick(View view) {
        Snackbar snackbar = Snackbar.make(activityCollapsingToolbarLayout,"已收藏...",Snackbar.LENGTH_LONG);
        snackbar.getView().setBackgroundColor(getResources().getColor(R.color.colorPrimary));
        snackbar.show();
    }
}

源码:
https://github.com/ListenerGao/MyTest/blob/master/app/src/main/java/com/listenergao/mytest/activity/CollapsingToolbarLayoutActivity.java