初识 Material Design

认识 Material Design

长久以来,Android 系统的 UI 风格一直难以统一,为了解决这个问题,Google 在2014年的 I/O 开发者大会上推出了一种新的 UI 设计语言Material Design,但此时的Material Design只是一套面向设计人员的设计规范,许多开发人员根本搞不清什么才是Material Design风格,于是在2015年的 I/O 开发者大会上,Google 又推出了Design Support库,将Material Design中最具代表性的控件和效果进行了封装,开发者只需要使用这些控件即可轻松实现Material Design风格的 APP。

认识 Material Components

Material Design官方网站上列出了 11 个Material Components,如图所示:

2018-01-02_144435.png

AppBarLayout

AppBarLayout是一个用于包裹应用栏的ViewGroup,它为应用栏提供了许多Material Design特性和交互,即对滚动的响应。

作为工具栏和其他视图的容器,AppBarLayout需要与CoordinatorLayout配合来响应滚动(AppBarLayout需要作为CoordinatorLayout的直接子View)。

AppBarLayout的每个子View都可以通过设置app:layout_scrollFlags属性来控制自身对于滚动的响应,该属性可选值为enterAlwaysenterAlwaysCollapsedexitUntilCollapsedscrollsnap

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
<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.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- Your scrolling content -->
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<android.support.v7.widget.Toolbar
...
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
...
app:layout_scrollFlags="scroll|enterAlways"/>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>

BottomNavigationView

BottomNavigationView用于创建底部导航栏,推荐当底部有3 - 5个导航页面时使用。

使用方法
  1. 创建一个至多包含 5 个导航页面的menu resource菜单资源文件(BottomNavigationView最多支持 5 个 item)
  2. 在布局文件中创建BottomNavigationView,并使用app:menu属性引入菜单资源文件
  3. 调用setOnNavigationItemSelectedListener()方法为每一个导航页面添加监听

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!-- menu resource 菜单资源文件 -->
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/action_search"
    android:title="@string/menu_search"
    android:icon="@drawable/ic_search" />
    <item android:id="@+id/action_settings"
    android:title="@string/menu_settings"
    android:icon="@drawable/ic_add" />
    <item android:id="@+id/action_navigation"
    android:title="@string/menu_navigation"
    android:icon="@drawable/ic_action_navigation_menu" />
    </menu>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <FrameLayout
    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">
    <!-- Main content -->
    <android.support.design.widget.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:itemBackground="@color/colorPrimary"
    app:itemIconTint="@color/white"
    app:itemTextColor="@color/white"
    app:menu="@menu/navigation_menu" />
    </FrameLayout>

BottomSheetBehavior

BottomSheetBehavior应用于CoordinatorLayout的子View,使其成为底部表单,用以显示底部表单,执行进入/退出动画,响应拖动/滑动手势。

底部表单有 5 种状态:

  • STATE_COLLAPSED
  • STATE_EXPANDED
  • STATE_DRAGGING
  • STATE_SETTLING
  • STATE_HIDDEN
使用方法

在布局文件中为CoordinatorLayout的直接子 View 添加属性:

  • app:layout_behavior=”android.support.design.widget.BottomSheetBehavior
  • app:behavior_hideable
  • app:behavior_peekHeight
  • app:behavior_skipCollapsed

或在代码中调用BottomSheetBehaviorsetState()方法

1
2
bottomSheetBehavior.setPeekHeight(300);
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);

CollapsingToolbarLayout

CollapsingToolbarLayout是一个提供了许多折叠工具栏视觉和交互效果的 ViewGroup,折叠工具栏需要CollapsingToolbarLayoutAppBarLayoutCoordinatorLayoutToolbar以及一个可滚动的View(例如RecyclerView) 组合实现。

使用方法

要将折叠工具栏添加到布局中,需要将CollapsingToolbarLayout放置在AppBarLayout中,然后将Toolbar和其他View作为子View添加到CollapsingToolbarLayout中。要使用CollapsingToolbarLayout的滚动效果需要确保视图结构位于CoordinatorLayout中。

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
<!-- 一个折叠工具栏的例子 -->
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Scrollable view here -->
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="@dimen/tall_toolbar_height">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleGravity="top"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
</android.support.design.widget.CoordinatorLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 一个带有 image 的折叠工具栏的例子 -->
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleGravity="top"
app:expandedTitleMarginStart="@dimen/shrine_toolbar_offset_start"
app:expandedTitleMarginTop="@dimen/shrine_toolbar_offset_top"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/shrine_toolbar_image_offset_top"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5"/>
<android.support.v7.widget.Toolbar
android:id="@+id/AppBar"
android:layout_width="match_parent"
android:layout_height="@dimen/shrine_toolbar_collapsed_height"
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>

CoordinatorLayout

CoordinatorLayout是用于协调子视图间的交互行为的通用容器

FloatingActionButton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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">
<!-- Main content -->
<android.support.design.widget.FloatingActionButton
android:id="@+id/floating_action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"/>
</android.support.design.widget.CoordinatorLayout>

修改图标:

  • android:src (属性)
  • setImageDrawable (方法)

修改大小:

  • app:fabSize (属性)
  • setSize (方法)

修改高度:

  • app:elevation (属性)
  • setCompatElevation (方法)

FloatingActionButton的默认颜色为主题中的colorAccent,若要修改颜色:

  • app:backgroundTint (属性)
  • setBackgroundTintList (方法)

响应点击事件:

1
2
3
4
5
6
7
8
9
FloatingActionButton floatingActionButton =
(FloatingActionButton) findViewById(R.id.floating_action_button);
floatingActionButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// Handle the click.
}
});

BottomSheetDialogFragment

NavigationView是一个将菜单资源文件显示为导航菜单的简单实现,通常与DrawerLayout配合使用以实现侧滑菜单。

1
2
3
4
5
6
7
8
<!-- 一个 NavigationView 的例子 -->
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start|left"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/my_navigation_items" />
  • app:menu 表示需要显示的菜单资源文件
  • app:headerLayout 表示NavigationView的头布局文件

使用setNavigationItemSelectedListener()来监听菜单项的点击事件。

通常可以直接在布局文件中为NavigationView添加头布局,但也可以在代码中通过addHeaderView(View)动态添加多个头布局,同时还可以通过getHeaderView(int)在运行时获得任何一个头布局。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 一个侧滑菜单的例子 -->
<android.support.v4.widget.DrawerLayout>
<android.support.design.widget.CoordinatorLayout>
<!-- Your content goes here -->
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start|left"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/my_navigation_items" />
</android.support.v4.widget.DrawerLayout>

Snackbar

Snackbar可以用来显示消息,与Toast类似,也会在显示后自动消失;同时,Snackbar还支持点击事件的响应。SnackbarCoordinatorLayout中的显示效果最好。

使用方法

Snackbar提供了静态的make()方法用以生成Snackbar,再调用show()方法显示该Snackbar,可供选择的显示时间有:

  • LENGTH_INDEFINITE
  • LENGTH_LONG
  • LENGTH_SHORT
1
2
3
4
//显示一段 message 的 Snackbar
View contextView = findViewById(R.id.context_view);
Snackbar.make(contextView, R.string.item_removed_message, Snackbar.LENGTH_SHORT).show();
1
2
3
4
5
6
7
8
9
//能够响应点击事件的 Snackbar
Snackbar.make(contextView, R.string.item_removed_message, Snackbar.LENGTH_LONG)
.setAction(R.string.undo, new OnClickListener() {
@Override
public void onClick(View v) {
// Respond to the click, such as by undoing the modification that caused
// this message to be displayed
})
});

默认的Action文本的颜色为主题的colorAccent,通过setActionTextColor()方法可修改Action文本的颜色。

TabLayout

TabLayout提供了一个水平布局来显示选项卡,TabLayout可以固定也可以滚动,每一个选项卡中要显示的视图应该都保存在ViewPager中,使用setupWithViewPager(ViewPager)TabLayoutViewPager绑定。

1
2
3
4
5
6
7
8
9
10
<android.support.v4.view.ViewPager
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top" />
</android.support.v4.view.ViewPager>

TextInputLayout

TextInputLayout提供了一种文字域的Material Design实现,通常与TextInputEditText一起使用。

1
2
3
4
5
6
7
8
9
10
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/hint_text"/>
</android.support.design.widget.TextInputLayout>

参考文章

Material Components

Android 详细分析AppBarLayout的五种ScrollFlags