Translucent System Bars-4.4新特性

Toolbar-5.0新特性

NavigationDrawer 简介

NavigationDrawer 是 Google 在 Material Design 中推出的一种侧滑导航栏设计风格。说起来很抽象,我们来看下网易云音乐侧滑导航栏的实现效果

NavigationDrawer和NavigationView-Android M新控件_Android开发

想有漂亮的 Material Design,Google 已提供 Android Design Support Library 可供使用。它支援 Android 2.1 或以上,提供不少好用的 UI element,可方便做到 Material Design Pattern 的效果。

为了实现这种效果,Google官方推出一个新控件 —— DrawerLayout 。而在 DrawerLayout 没诞生之前,需求中需要实现侧滑导航效果时,我们通常会选择去选择一些成熟的第三方开源库(如最有名的 SlidingMenu)来实现类似的效果。

既然官方有提供,我们为何不使用呢? 不用引入第三方的jar,避免65536(你懂得),还能减少APP的体积,关键是使用起来简单,何乐而不为之呢?


DrawerLayout基本使用

英文666的童鞋可以查看这里How To Make Material Design Navigation Drawer With Header View

一般情况下,在DrawerLayout布局下只会存在两个子布局:

  1. 内容布局
  2. 侧滑菜单布局

这两个布局的关键在于 android:layout_gravity属性的设置。

如果你把其中一个子布局设置成了左侧滑菜单,只需要设置 android:layout_gravity=”start” 即可(也可以是left, 右侧滑为end或者right)。
没有设置的布局 自然成为了 内容布局

对,就这么简单…..按照常规,先上效果图,然后上code

效果图

NavigationDrawer和NavigationView-Android M新控件_Android教程_02

Code

activity_naviation_drawer_base_use.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


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

        
        <include            android:id="@+id/tv_content"
            layout="@layout/drawer_content_layout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

        
        <include            layout="@layout/drawer_menu_layout"
            android:layout_width="250dp"
            android:layout_height="match_parent"
            android:layout_gravity="start" />

        
        <include            layout="@layout/drawer_menu_layout"
            android:layout_width="250dp"
            android:layout_height="match_parent"
            android:layout_gravity="end" />


    android.support.v4.widget.DrawerLayout>RelativeLayout>

 

drawer_content_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="setScrimColor: " />

        <RadioGroup            android:id="@+id/rg_scrim_color"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <RadioButton                android:id="@+id/rbtn_pink"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/pink" />

            <RadioButton                android:id="@+id/rbtn_green"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/green" />

            <RadioButton                android:id="@+id/rbtn_blue"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:drawableLeft="@mipmap/blue" />

        RadioGroup>
    LinearLayout>

    <LinearLayout        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:gravity="center_vertical"
        android:orientation="horizontal">

        <TextView            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="openDrawer: " />

        <RadioGroup            android:id="@+id/rg_open_drawer"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

            <RadioButton                android:id="@+id/rbtn_from_left"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="left | start" />

            <RadioButton                android:id="@+id/rbtn_from_right"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="right | end" />

        RadioGroup>
    LinearLayout>LinearLayout>

 

drawer_menu_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="250dp"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/color_f5f5f5"
        android:gravity="center"
        android:text="@string/simple_navigation_drawer" />LinearLayout>

 

NaviationDrawerBaseUseAct.java

package com.turing.navigationdrawer;import android.os.Bundle;import android.support.v4.widget.DrawerLayout;import android.support.v7.app.AppCompatActivity;import android.view.Gravity;import android.view.View;import android.widget.RadioGroup;import android.widget.Toast;public class NaviationDrawerBaseUseAct extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener{

    private DrawerLayout drawerLayout ;    private RadioGroup rg_setScrimColor ,rg_openDrawer ;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_naviation_drawer_base_use);

        initView();
        initEvents();

    }    private void initView() {        //DrawerLayout
        drawerLayout = (DrawerLayout) findViewById(R.id.simple_navigation_drawer);        //RadioGroup
        rg_setScrimColor = (RadioGroup) findViewById(R.id.rg_scrim_color);
        rg_openDrawer = (RadioGroup) findViewById(R.id.rg_open_drawer);


    }    private void initEvents() {        //监听DrawerLayout的侧滑
        drawerLayout.setDrawerListener(new DrawerLayout.DrawerListener() {            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {

            }            @Override
            public void onDrawerOpened(View drawerView) {
                Toast.makeText(NaviationDrawerBaseUseAct.this, "onDrawerOpened", Toast.LENGTH_SHORT).show();
            }            @Override
            public void onDrawerClosed(View drawerView) {
                Toast.makeText(NaviationDrawerBaseUseAct.this, "onDrawerClosed", Toast.LENGTH_SHORT).show();
            }            @Override
            public void onDrawerStateChanged(int newState) {

            }
        });        // RadioGroup 监听事件
        rg_setScrimColor.setOnCheckedChangeListener(this);
        rg_openDrawer.setOnCheckedChangeListener(this);

    }    /**
     *  RadioButton被选中后的操作
     * @param group
     * @param checkedId
     */
    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {        switch (checkedId){            case R.id.rbtn_pink:
                drawerLayout.setScrimColor(getResources().getColor(R.color.color_e81d62));                break;            case R.id.rbtn_green:
                drawerLayout.setScrimColor(getResources().getColor(R.color.color_4bae4f));                break;            case R.id.rbtn_blue:
                drawerLayout.setScrimColor(getResources().getColor(R.color.color_2095f2));                break;            case R.id.rbtn_from_left:
                drawerLayout.openDrawer(Gravity.LEFT);//打开菜单栏
                break;            case R.id.rbtn_from_right:
                drawerLayout.openDrawer(Gravity.RIGHT);                break;            default:                break;
        }
    }
}

 

注意事项

  • DrawerLayout 为 v4包中的 android.support.v4.widget.DrawerLayout
  • DrawerLayout的监听事件 new DrawerLayout.DrawerListener(){…}
  • Google为我们提供了DrawerLayout常用的API,比如打开或者关闭侧滑栏、控制侧滑栏的方向、设置滑动时渐变的阴影颜色和监听滑动事件等,详见官方API
  • DrawerLayout 中的android:layout_width需要设置成match_parent,不能设置成wrap_content,否则会抛出 DrawerLayout must be measured with MeasureSpec.EXACTLY error
  • -

效果图

NavigationDrawer和NavigationView-Android M新控件_Android开发_03


NavigationView

官方文档

官方文档

Represents a standard navigation menu for application. The menu contents can be populated by a menu resource file.

NavigationView is typically placed inside a DrawerLayout.

 <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/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true">

     

     <android.support.design.widget.NavigationView         android:id="@+id/navigation"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:menu="@menu/my_navigation_items" />
 android.support.v4.widget.DrawerLayout>

 

概述

在Google推出NavigationDrawer设计中,NavigationView和DrawerLayout是官方推荐的最佳组合。

NavigationView是一个导航菜单框架,使用menu资源填充数据,使我们可以更简单高效的实现导航菜单。它提供了不错的默认样式、选中项高亮、分组单选、分组子标题、以及可选的Header.

在使用NavigationView之前,因为它Android Design Support Library(Material Design的兼容包)中,所以我们需要在build.gradle中加入 compile ‘com.android.support:design:23.1.1’

apply plugin: 'com.android.application'android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "com.turing.navigationdrawer"
        minSdkVersion 10
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.1.1'
    compile 'com.android.support:design:23.1.1'}

 

引用注意事项:

  • 工程配置的 compileSdkVersion 是 23 ,所以需要引入 com.android.support:design:23.x.x 的版本。需要吐槽的是,这里如果你引入了 com.android.support:design:23.1.0 ,工程运行后 NavigationView 会报一个 android.view.InflateException:xxxxxx 的错误

运行效果

NavigationDrawer和NavigationView-Android M新控件_Android开发_04

Code

最主要的两个属性分别是:

  • app:headerLayout接收一个layout,作为导航菜单顶部的Header,可选项。
  • app:menu接收一个menu,作为导航菜单的菜单项,几乎是必选项,不然这个控件就失去意义了。但也可以在运行时动态改变menu属性。
  • 用于NavigationView的典型menu文件,应该是一个可选中菜单项的集合。其中checked=”true”的item将会高亮显示,这可以确保用户知道当前选中的菜单项是哪个。item的选中状态也可以在代码中设置。

activity_navigation_view_base_use.xml

<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/drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/color_31c27c">

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

        <TextView            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="NavigationDrawerContent" />
    LinearLayout>

    <android.support.design.widget.NavigationView        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_drawer_header"
        app:menu="@menu/navigation_drawer_menu" />android.support.v4.widget.DrawerLayout>

 

navigation_drawer_header.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    android:background="@color/color_512da8">

    <TextView        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_margin="10dp"
        android:text="HeaderLayout"
        android:textColor="@android:color/white"
        android:textSize="18sp" />RelativeLayout>

 

menu/navigation_drawer_menu.xml

在menu目录下

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item            android:id="@+id/item_green"
            android:icon="@mipmap/green"
            android:title="Green" />
        <item            android:id="@+id/item_blue"
            android:icon="@mipmap/blue"
            android:title="Blue" />
        <item            android:id="@+id/item_pink"
            android:icon="@mipmap/pink"
            android:title="Pink" />
    group>

    <item android:title="SubItems">
        <menu>
            <item                android:id="@+id/subitem_01"
                android:icon="@mipmap/ic_launcher"
                android:title="SubItem01" />
            <item                android:id="@+id/subitem_02"
                android:icon="@mipmap/ic_launcher"
                android:title="SubItem02" />
            <item                android:id="@+id/subitem_03"
                android:icon="@mipmap/ic_launcher"
                android:title="SubItem03" />
        menu>
    item>

    <item android:title="SubItems">
        <menu>
            <item                android:id="@+id/subitem_04"
                android:icon="@mipmap/ic_launcher"
                android:title="SubItem04" />
            <item                android:id="@+id/subitem_05"
                android:icon="@mipmap/ic_launcher"
                android:title="SubItem05" />
            <item                android:id="@+id/subitem_06"
                android:icon="@mipmap/ic_launcher"
                android:title="SubItem06" />
        menu>
    item>menu>

 

NavigationViewBaseUseAct.java

package com.turing.navigationdrawer;import android.os.Bundle;import android.support.design.widget.NavigationView;import android.support.v4.widget.DrawerLayout;import android.support.v7.app.AppCompatActivity;import android.view.MenuItem;import android.view.Window;import android.widget.Toast;public class NavigationViewBaseUseAct extends AppCompatActivity {

    private DrawerLayout drawerLayout;    private NavigationView navigationView;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_navigation_view_base_use);


        drawerLayout = (DrawerLayout) findViewById(R.id.drawer);
        navigationView = (NavigationView) findViewById(R.id.navigation_view);        //设置菜单图标恢复本来的颜色,不设置的话 是没有颜色的......
        navigationView.setItemIconTintList(null);        // 设置监听事件
        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {            @Override
            public boolean onNavigationItemSelected(MenuItem item) {                switch (item.getItemId()){                    case R.id.subitem_01:
                        Toast.makeText(NavigationViewBaseUseAct.this, "sub item 01", Toast.LENGTH_SHORT).show();                        break;                    default:                        break;
                }                // 关闭drawerlayout
                drawerLayout.closeDrawers();                return true;
            }
        });
    }
}

 

注意事项:

-第一次运行代码的时候,图标的颜色居然都是灰色的….代码中可以调用下面这个APInavigationView.setItemIconTintList(null);//设置菜单图标恢复本来的颜色

  • NavigationView 基本已经规定设置好了大小距离,留给我们可以改动的空间并不多。详见官方文档(自备梯子)如果你想调整一下菜单的布局宽高之类的,基本是不可能的了

仿网易云音乐的 NavigationDrawer 实现

官方运行图

NavigationDrawer和NavigationView-Android M新控件_Android教程_05

里面的图标,可以下载APP,解压后,去文件夹里取出来~

主要就是一个线性布局的菜单并结合了 Translucent System Bar 的特性。

Code

activity_cloud_music.xml

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/color_cd3e3a">

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

        <TextView            android:layout_width="match_parent"
            android:layout_height="65dp"
            android:background="@color/color_cd3e3a"
            android:gravity="center"
            android:text="网易云音乐"
            android:textColor="@android:color/white"
            android:textSize="18sp" />

        <LinearLayout            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/white"
            android:orientation="vertical">

        LinearLayout>
    LinearLayout>

    <LinearLayout        android:id="@+id/navigation_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@android:color/white"
        android:fitsSystemWindows="true"
        android:orientation="vertical"
        >

        <ImageView            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/topinfo_ban_bg" />

        <LinearLayout            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/topmenu_icn_msg" />

            <TextView                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="我的消息"
                android:textColor="@android:color/black"
                android:textSize="15sp" />
        LinearLayout>

        <LinearLayout            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/topmenu_icn_store" />

            <TextView                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="积分商城"
                android:textColor="@android:color/black"
                android:textSize="15sp" />
        LinearLayout>

        <LinearLayout            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/topmenu_icn_member" />

            <TextView                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="付费音乐包"
                android:textColor="@android:color/black"
                android:textSize="15sp" />
        LinearLayout>

        <LinearLayout            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <ImageView                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/topmenu_icn_free" />

            <TextView                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="在线听歌免流量"
                android:textColor="@android:color/black"
                android:textSize="15sp" />
        LinearLayout>
    LinearLayout>android.support.v4.widget.DrawerLayout>

 

沉浸式主题样式,需要在不同SDK的values目录下,设置样式,在Manifest.xml中通过 android:theme引用主题,别忘了 android:fitsSystemWindows=”true”。

效果图

NavigationDrawer和NavigationView-Android M新控件_Android开发_06


左上角的导航动画效果实现

效果

NavigationDrawer和NavigationView-Android M新控件_Android开发_07

ActionBarDrawerToggle实现

之前想要引入这种效果,都是来自第三方的开源代码,诸如下面两个比较有名的:

自从MaterialDesign出来之后,就再也需要了,Google提供了ActionBarDrawerToggle

activity_animation_left_top.xml

<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.v7.widget.Toolbar        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
        android:theme="@style/Theme.Drawer.ArrowAnimation" />

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

        <TextView            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="NavigationAnimation" />

        <LinearLayout            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/white"
            android:orientation="vertical">

            <TextView                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="Drawer" />
        LinearLayout>
    android.support.v4.widget.DrawerLayout>LinearLayout>

 

AnimationLeftTopAct.java

package com.turing.navigationdrawer;import android.content.res.Configuration;import android.os.Bundle;import android.support.v4.widget.DrawerLayout;import android.support.v7.app.ActionBarDrawerToggle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.view.MenuItem;import android.view.Window;public class AnimationLeftTopAct extends AppCompatActivity {

    private Toolbar mToolbar;    private DrawerLayout mDrawerLayout;    private ActionBarDrawerToggle mActionBarDrawerToggle;    @Override
    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);
        supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_animation_left_top);

        mToolbar = (Toolbar) findViewById(R.id.toolbar);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);
        mActionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, mToolbar, R.string.open, R.string.close);
        mDrawerLayout.setDrawerListener(mActionBarDrawerToggle);
    }    @Override
    protected void onPostCreate(Bundle savedInstanceState) {        super.onPostCreate(savedInstanceState);
        mActionBarDrawerToggle.syncState();
    }    @Override
    public boolean onOptionsItemSelected(MenuItem item) {        if (mActionBarDrawerToggle.onOptionsItemSelected(item)) {            return true;
        }        return super.onOptionsItemSelected(item);
    }    @Override
    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);
        mActionBarDrawerToggle.onConfigurationChanged(newConfig);
    }
}

 

material-menu 开源的动画效果

material-menu

NavigationDrawer和NavigationView-Android M新控件_Android教程_08

比 NavigationView 更好的选择

MaterialDrawer
NavigationDrawer和NavigationView-Android M新控件_Android开发_09

NavigationDrawer和NavigationView-Android M新控件_Android教程_10


参考文章:http://www.jianshu.com/p/c8cbeb7ea43a#
感谢D_clork