Translucent System Bars-4.4新特性
NavigationDrawer 简介NavigationDrawer 是 Google 在 Material Design 中推出的一种侧滑导航栏设计风格。说起来很抽象,我们来看下网易云音乐侧滑导航栏的实现效果
想有漂亮的 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布局下只会存在两个子布局:
- 内容布局
- 侧滑菜单布局
这两个布局的关键在于 android:layout_gravity属性的设置。
如果你把其中一个子布局设置成了左侧滑菜单,只需要设置 android:layout_gravity=”start” 即可(也可以是left, 右侧滑为end或者right)。
没有设置的布局 自然成为了 内容布局
对,就这么简单…..按照常规,先上效果图,然后上code
效果图
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
- -
效果图
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 的错误
运行效果
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 实现
官方运行图
里面的图标,可以下载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”。
效果图
左上角的导航动画效果实现
效果
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 开源的动画效果
比 NavigationView 更好的选择
参考文章:http://www.jianshu.com/p/c8cbeb7ea43a#
感谢D_clork