Material实践Toolbar和DrawerLayout的使用

设置Theme及定义基本颜色

根据官方设计规范(Color),定义一些用到的颜色:

Toolbars and larger color blocks should use the primary 500 color, which should be the main color of your app. The status bar should be the darker 700 tint of your primary color.

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<!--values/colors.xml -->
<resources>
<color name="color_primary">#3F51B5</color>
<color name="color_primary_dark">#303F9F</color>
<color name="color_accent">#E91E63</color>
</resources>

对Lollipop及以下的安卓版本使用不同的styles.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- values/styles.xml -->
<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="AppTheme.Base">
<!-- Customize your theme here. -->
</style>

<style name="AppTheme.Base" parent="Theme.AppCompat.NoActionBar">
<item name="colorPrimary">@color/color_primary</item>
<item name="colorPrimaryDark">@color/color_primary_dark</item>
<item name="colorAccent">@color/color_accent</item>
</style>

</resources>
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<!-- values-v21/styles.xml -->
<resources>
<style name="AppTheme" parent="AppTheme.Base">
<item name="android:colorPrimary">@color/color_primary</item>
<item name="android:colorPrimaryDark">@color/color_primary_dark</item>
<item name="android:colorAccent">@color/color_accent</item>
</style>
</resources>

使用Toolbar代替ActionBar

  1. 使用Theme.AppCompat.NoActionBar或者Theme.AppCompat.Light.NoActionBar将系统的ActonBar隐藏
  2. 定义一个app_bar.xml的布局文件,里面包含一个ToolBar控件
  3. 使用在你的layout中添加Toolbar
  4. Activity中使用findViewById实例化Toolbar
  5. 使用setSupportActionBar()引入实例化的Toolbar
  6. 自定义app:themeapp:popupTheme,如果有需要的话
  7. 自定义其他特性,直接使用Toobar的实例或者使用getSupportActionBar()
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<!-- layout/app_bar.xml -->
<android.support.v7.widget.Toolbar 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="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">
</android.support.v7.widget.Toolbar>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- activity_main.xml -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<include
layout="@layout/app_bar"
android:id="@+id/app_bar" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:layout_below="@id/app_bar">

</LinearLayout>

</RelativeLayout>

onCreate方法中实例化Toolbar对象

1
2
3
4
5
6
7
8
Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
}

看看效果:

使用Navigation Drawer侧滑菜单

  1. 使用DrawerLayout包含两个子布局,一个是你的内容主布局,一个是侧边布局
  2. 在代码中初始化DrawerLayout
  3. 创建一个ActionBarDrawerToggle的实例,并指定Activity、DrawerLayout、Toolbar、Open和Close的字符串值
  4. 使用ActionBarDrawerTogglesyncState()方法同步汉堡菜单

创建一个空的FragmentNavigationDrawerFragment作为侧边栏的布局,修改主布局文件,使用DrawerLayout包含两个子布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!-- activity_main.xml -->
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schems.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<include
layout="@layout/app_bar"
android:id="@+id/app_bar" />

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:layout_below="@id/app_bar">

</FrameLayout>

</RelativeLayout>

<fragment
android:id="@+id/fragment_navigation_drawer"
android:layout_width="280dp"
android:layout_gravity="start"
android:layout_height="match_parent"
app:layout="@layout/fragment_navigation_drawer"
tools:layout="@layout/fragment_navigation_drawer"
android:name="cn.treize.formaterialtest.NavigationDrawerFragment" />

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

MainActivity.java中:

1
2
3
4
5
6
7
8
9
10
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);

NavigationDrawerFragment drawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp((DrawerLayout)findViewById(R.id.drawer_layout), toolbar);
}

修改NavigationDrawerFragment.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package cn.treize.formaterialtest;


import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


/**
* A simple {@link Fragment} subclass.
* 注意import的是v4里面的Fragment
* import android.support.v4.app.Fragment;
*/
public class NavigationDrawerFragment extends Fragment {

private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;

public NavigationDrawerFragment() {
// Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
}


public void setUp(DrawerLayout drawerlayout, Toolbar toolbar) {
mDrawerLayout = drawerlayout;
mDrawerToggle = new ActionBarDrawerToggle(getActivity(),
drawerlayout,toolbar,R.string.drawer_open,R.string.drawer_close){
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}

@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
};

mDrawerLayout.setDrawerListener(mDrawerToggle);

// syncState同步汉堡菜单
drawerlayout.post(new Runnable() {
@Override
public void run() {
mDrawerToggle.syncState();
}
});
}
}

NavigationDrawerFragment的布局文件,这里只是个空的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- fragment_navigation_drawer.xml -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#CCC"
tools:context="cn.treize.formaterialtest.NavigationDrawerFragment">

<!-- TODO: Update blank fragment layout -->
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="@string/hello_blank_fragment" />

</FrameLayout>
`

strings.xml中定义ActonBarDrawerToggle的Open和Close字符值:

1
2
<string name="drawer_open">Open</string>
<string name="drawer_close">Close</string>

看看效果:

可以看到侧滑菜单遮住了Toolbar,如果我想要另一种效果呢,也就是侧滑菜单在Toolbar下面。方法很简单,把Toobar的layout和drawerlayout放到同级布局文件里面即可。下面创建一个新的布局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?xml version="1.0" encoding="utf-8"?>
<!-- activity_main_appbar.xml -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent">

<include
layout="@layout/app_bar"
android:id="@+id/app_bar" />

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

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff">

</FrameLayout>

</RelativeLayout>

<fragment
android:id="@+id/fragment_navigation_drawer"
android:layout_width="280dp"
android:layout_gravity="start"
android:layout_height="match_parent"
app:layout="@layout/fragment_navigation_drawer"
tools:layout="@layout/fragment_navigation_drawer"
android:name="cn.treize.formaterialtest.NavigationDrawerFragment" />

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

</LinearLayout>

在MainActivity中引用该布局,看看效果:

我们看到有些应用在侧边栏展开的时候,Toobar会逐渐变暗,这个效果只需要在ActonBarDrawerToggle实例中实现该方法就行了:

1
2
3
4
5
6
7
@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
super.onDrawerSlide(drawerView, slideOffset);
if (slideOffset < 0.6) {
toolbar.setAlpha(1 - slideOffset);
}
}

效果也是杠杠的:

听说,赞赏了的人都变美了哦~
0%