Ding

DrawerLayout、CoordinatorLayout、CollapsingToolbarLayout的使用--AndroidSupportDesign练手

先po一张效果图

PS:原谅题主的懒惰吧..

看着是不是很酷炫,那是因为5.0的动画做得好,代码其实没有多少,搞清楚这个布局的层次关系很重要。

废话不多说了,先来看布局文件

最外层是一个DrawerLayout,它里面可以嵌套(一个?)container和多个drawer

在这个demo中DrawerLayout包含了一个CoordinatorLayout , ListView , NavigationView

CoordinatorLayout 作为 container的根布局

listView和navigationview作为DarwerLayout中的darwer

在container中用CoordinatorLayout目的是为了我们在滑动recyclerview时,让顶部的appbarlayout中的组件产生响应

appbarlayout中的CollapsingToolbarLayout是用来控制toolbar和banner图片的响应效果

特别注意:为了使得Toolbar可以滑动,我们必须还得有个条件,就是CoordinatorLayout布局下包裹一个可以滑动的布局,比如 RecyclerView,NestedScrollView(经过测试,ListView,ScrollView不支持)具有滑动效果的组件。

下面的就是drawerLayout的使用注意事项了:

按情理来说,一个drawerLayout添加一个drawer就够了,可是脑洞一开,想着多加一个会怎样,尝试之后发现很好玩,以后可以各种乱入drawer了,哈哈哈。

因为做毕设的时候用的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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
<?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"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="@android:color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/banner"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="banner"
android:scaleType="fitXY"
android:src="@mipmap/banner"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5" />
<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/transparent"
app:layout_collapseMode="pin" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_vertical_margin"
android:src="@mipmap/ic_action_web_site"
app:borderWidth="0dp"
app:elevation="@dimen/fab_elevation"
app:layout_anchor="@id/app_bar_layout"
app:layout_anchorGravity="end|bottom"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7"
app:pressedTranslationZ="@dimen/fab_translation_z_pressed"
app:rippleColor="?attr/colorPrimary" />
</android.support.design.widget.CoordinatorLayout>
<ListView
android:id="@+id/id_lv_left_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="end"
android:paddingTop="0dp"
android:background="#ffffffff"
android:clipToPadding="false"
android:divider="@null"
android:listSelector="?attr/selectableItemBackground"
/>
<!--<include-->
<!--android:layout_width="match_parent"-->
<!--android:layout_height="match_parent"-->
<!--android:layout_gravity="start"-->
<!--android:paddingTop="0dp"-->
<!--android:background="#ffffffff"-->
<!--android:clipToPadding="false"-->
<!--android:id="@+id/custom_drawer"-->
<!--layout="@layout/layout_listview_drawer" />-->
<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/drawer_header"
app:menu="@menu/menu_navigation_items" />
</android.support.v4.widget.DrawerLayout>

Activity文件:

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
package com.anhry.hcol.support.design.activity;
import android.os.Bundle;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import com.anhry.hcol.support.design.adapter.LeftMenuListAdapter;
import com.anhry.hcol.support.design.adapter.MenuItemAdapter;
import com.anhry.hcol.support.design.module.LvMenuItem;
import com.yanbober.support_library_demo.R;
import com.yanbober.support_library_demo.RecyclerViewAdapter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author HCol
* @email 282386589@qq.com
* @create 2015/8/25
* @modify 2015年8月29日17:29:04
*/
public class DesignDemoActivity extends AppCompatActivity {
/**
* views
*/
private DrawerLayout mDrawerLayout;
private CoordinatorLayout mCoordinatorLayout;
private AppBarLayout mAppBarLayout;
private CollapsingToolbarLayout mCollapsingToolbarLayout;
private ImageView mImageView;
private Toolbar mToolbar;
private RecyclerView mRecyclerView;
private NavigationView mNavigationView;
private FloatingActionButton mFloatingActionButton;
private ImageView mRightNavigationBtn;
private CoordinatorLayout mCustomDrawer;
private RecyclerView leftMenuList;
private ListView mLvLeftMenu;
/**
* members
*/
private RecyclerViewAdapter mAdapter;
private LinearLayoutManager mRecyclerLayoutManager;
private LeftMenuListAdapter mLeftMenuListAdapter;
private List<LvMenuItem> dataSource;
private static final String BTN_RIGHT_MENU_TAG = "tag";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initViews();
}
/**
* init views
*/
private void initViews() {
setContentView(R.layout.activity_my_design);
/* 抽屉形式界面的的两个布局控件
*
* DrawerLayout 做根布局使用
* 因为要显示的内容界面和抽屉视图(NavigationView)是包含在此layout之下的
*
* NavigationView 抽屉布局中的抽屉视图,有源码分析他的实现其实就是一个ListView
* 而这里用的是原生的组件,所以在Menu目录下配置好要显示的条目,引用即可,非常方便.
*
* ref:http://blog.csdn.net/lmj623565791/article/details/46405409
*
* */
// 原生DrawerLayout
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// 利用ListView仿制的Drawer
mLvLeftMenu = (ListView) findViewById(R.id.id_lv_left_menu);
setUpDrawer();
// 不用在意这一块
// mCustomDrawer = (CoordinatorLayout) findViewById(R.id.custom_drawer);
// leftMenuList = (RecyclerView) findViewById(R.id.rv_left_menu);
// dataSource = new ArrayList<>(
// Arrays.asList(
// new LvMenuItem(R.mipmap.ic_action_web_site, "Home"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Messages"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Friends"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Discussion"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Discussion"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Discussion"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Discussion"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Discussion"),
// new LvMenuItem(),
// new LvMenuItem("Sub Items"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Sub Item 1"),
// new LvMenuItem(R.mipmap.ic_action_web_site, "Sub Item 2")
// ));
// mLeftMenuListAdapter = new LeftMenuListAdapter(this, dataSource);
// mRecyclerLayoutManager = new LinearLayoutManager(this);
// leftMenuList.setAdapter(mLeftMenuListAdapter);
// leftMenuList.setLayoutManager(mRecyclerLayoutManager);
mNavigationView = (NavigationView) findViewById(R.id.navigation_view);
mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
mDrawerLayout.closeDrawers();
return true;
}
});
/* 下面就是抽屉布局中[内容布局]的重点了
*
* CoordinatorLayout 协调者布局
* AppBarLayout 导航栏布局
* CollapsingToolbarLayout ToolBar的可坍塌布局
*
* 首先,这三个布局有什么用呢?
*
* CoordinatorLayout
* 官方文档介绍说是一个增强版的FrameLayout
* 有两种主要的用途:
* 1. 作为一个顶层布局文件来使用
* 2. 作为一个有[多个互动视图]的容器
* 就是当某一视图有特殊行为动作时,其他子视图会进行相应的动作反应。INTERACTION
*
* AppBarLayout
* 一个模块化的布局文件,可以用来装载一切属于AppBar的组件
*
* CollapsingToolbarLayout
*
* CollapsingToolbarLayout is a wrapper for Toolbar which implements a collapsing app bar.
* It is designed to be used as a direct child of a AppBarLayout.
*
* 官方说,它的诞生主要是用来为toolbar锦上添花用的
* 被设计来作为AppBarLayout的亲儿子来使用
*
* */
mCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.main_content);
mAppBarLayout = (AppBarLayout) findViewById(R.id.app_bar_layout);
mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout);
mImageView = (ImageView) findViewById(R.id.banner);
mToolbar = (Toolbar) findViewById(R.id.tool_bar);
// 创建右边导航按钮
ensureRightButtonView();
mToolbar.setNavigationIcon(R.mipmap.ic_drawer);
mToolbar.addView(mRightNavigationBtn);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDrawerLayout.openDrawer(GravityCompat.START);
}
});
mCollapsingToolbarLayout.setTitle("CollapsingTitle");
/* init RecyclerView */
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new RecyclerViewAdapter(this);
mRecyclerView.setAdapter(mAdapter);
mRecyclerLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mRecyclerLayoutManager);
mFloatingActionButton = (FloatingActionButton)findViewById(R.id.fab);
mFloatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(mRecyclerView , "papa i'm here" , Snackbar.LENGTH_LONG).show();
}
});
}
private void setUpDrawer() {
LayoutInflater inflater = LayoutInflater.from(this);
mLvLeftMenu.addHeaderView(inflater.inflate(R.layout.drawer_header, mLvLeftMenu, false));
mLvLeftMenu.setAdapter(new MenuItemAdapter(this));
mLvLeftMenu.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
mDrawerLayout.closeDrawers();
}
});
}
private void ensureRightButtonView() {
if (mRightNavigationBtn == null) {
mRightNavigationBtn = new ImageButton(this, null,
android.support.v7.appcompat.R.attr.toolbarNavigationButtonStyle);
final Toolbar.LayoutParams lp = generateDefaultLayoutParams();
lp.gravity = GravityCompat.END | (Gravity.TOP & Gravity.VERTICAL_GRAVITY_MASK);
mRightNavigationBtn.setImageResource(R.mipmap.ic_drawer);
mRightNavigationBtn.setLayoutParams(lp);
mRightNavigationBtn.setTag(BTN_RIGHT_MENU_TAG);
mRightNavigationBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDrawerLayout.openDrawer(GravityCompat.END);
}
});
}
}
private Toolbar.LayoutParams generateDefaultLayoutParams() {
return new Toolbar.LayoutParams(Toolbar.LayoutParams.WRAP_CONTENT, Toolbar.LayoutParams.WRAP_CONTENT);
}
}

drawer head:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#000000"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="13dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/icon_people" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:text="UserName"
android:textColor="?attr/colorAccent"
android:textSize="24sp" />
</LinearLayout>

ListViewAdapter:

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
public class MenuItemAdapter extends BaseAdapter {
private final int mIconSize;
private LayoutInflater mInflater;
private Context mContext;
public MenuItemAdapter(Context context) {
mInflater = LayoutInflater.from(context);
mContext = context;
mIconSize = context.getResources().getDimensionPixelSize(R.dimen.abc_dialog_padding_material);//24dp
}
private List<LvMenuItem> mItems = new ArrayList<LvMenuItem>(
Arrays.asList(
new LvMenuItem(R.mipmap.ic_action_web_site, "Home"),
new LvMenuItem(R.mipmap.ic_action_web_site, "Messages"),
new LvMenuItem(R.mipmap.ic_action_web_site, "Friends"),
new LvMenuItem(R.mipmap.ic_action_web_site, "Discussion"),
new LvMenuItem(),
new LvMenuItem("Sub Items"),
new LvMenuItem(R.mipmap.ic_action_web_site, "Sub Item 1"),
new LvMenuItem(R.mipmap.ic_action_web_site, "Sub Item 2")
));
@Override
public int getCount() {
return mItems.size();
}
@Override
public Object getItem(int position) {
return mItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getViewTypeCount() {
return 3;
}
@Override
public int getItemViewType(int position) {
return mItems.get(position).type;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LvMenuItem item = mItems.get(position);
switch (item.type) {
case LvMenuItem.TYPE_NORMAL:
if (convertView == null) {
convertView = mInflater.inflate(R.layout.design_drawer_item, parent,
false);
}
TextView itemView = (TextView) convertView;
itemView.setText(item.name);
Drawable icon = mContext.getResources().getDrawable(item.icon);
setIconColor(icon);
if (icon != null) {
icon.setBounds(0, 0, mIconSize, mIconSize);
TextViewCompat.setCompoundDrawablesRelative(itemView, icon, null, null, null);
}
break;
case LvMenuItem.TYPE_NO_ICON:
if (convertView == null) {
convertView = mInflater.inflate(R.layout.design_drawer_item_subheader,
parent, false);
}
TextView subHeader = (TextView) convertView;
subHeader.setText(item.name);
break;
case LvMenuItem.TYPE_SEPARATOR:
if (convertView == null) {
convertView = mInflater.inflate(R.layout.design_drawer_item_separator,
parent, false);
}
break;
}
return convertView;
}
public void setIconColor(Drawable icon) {
int textColorSecondary = android.R.attr.textColorSecondary;
TypedValue value = new TypedValue();
if (!mContext.getTheme().resolveAttribute(textColorSecondary, value, true)) {
return;
}
int baseColor = mContext.getResources().getColor(value.resourceId);
icon.setColorFilter(baseColor, PorterDuff.Mode.MULTIPLY);
}
}

Item:

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
public class LvMenuItem {
public LvMenuItem(int icon, String name) {
this.icon = icon;
this.name = name;
if (icon == NO_ICON && TextUtils.isEmpty(name)) {
type = TYPE_SEPARATOR;
} else if (icon == NO_ICON) {
type = TYPE_NO_ICON;
} else {
type = TYPE_NORMAL;
}
if (type != TYPE_SEPARATOR && TextUtils.isEmpty(name)) {
throw new IllegalArgumentException("you need set a name for a non-SEPARATOR item");
}
}
public LvMenuItem(String name) {
this(NO_ICON, name);
}
public LvMenuItem() {
this(null);
}
public static final int NO_ICON = 0;
public static final int TYPE_NORMAL = 0;
public static final int TYPE_NO_ICON = 1;
public static final int TYPE_SEPARATOR = 2;
public int type;
public String name;
public int icon;
}

Item的资源文件:

design_drawer_item_separator:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View android:layout_width="match_parent"
android:layout_height="1dp"
android:background="?android:attr/listDivider"/>
</FrameLayout>

design_drawer_item_subheader:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
android:gravity="center_vertical|start"
android:maxLines="1"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="?android:textColorSecondary"/>

design_drawer_item:

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="?attr/listPreferredItemHeightSmall"
android:paddingLeft="?attr/listPreferredItemPaddingLeft"
android:paddingRight="?attr/listPreferredItemPaddingRight"
android:drawablePadding="32dp"
android:gravity="center_vertical|start"
android:maxLines="1"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="?android:attr/textColorPrimary"/>

参考资料:

http://www.2cto.com/kf/201506/409067.html

http://www.open-open.com/lib/view/open1433385856119.html#_label8

http://blog.csdn.net/lmj623565791/article/details/46405409

PS:为什么放多个drawer,而drawerLayout打开drawer的时候不会混乱呢?

没事就看看源码,反正又不要钱..

你的认可是我最大的动力!