[关闭]
@ltlovezh 2016-08-05T12:46:34.000000Z 字数 9957 阅读 565

Android Material Design

MaterialDesign


Android Material Design设计规范已经出来很久了,但是国内APP貌似很少使用啊。而且Android Design Support Library提供了良好的兼容性,可以直接向下兼容到Android2.2,完全可以一试哈。本文简单介绍下Design库提供的一些组件,方便日后查询使用。

Snackbar

Snackbar是一种介于Toast和AlertDialog之间的轻量级控件,可以很方便的提供消息提示和动作反馈。

Snackbar的使用方式和Toast类似,但与Toast不同的是,Snackbar可以带有按钮,并且只会出现在屏幕底部;Snackbar支持右滑删除,类似通知栏的消息;如果用户没做任何操作,Snackbar在到达设定的时间后会自动消失。

使用Snackbar的代码很简单,如下所示:

  1. Snackbar.make(myView,
  2. "This is Snackbar",
  3. Snackbar.LENGTH_LONG)
  4. .setAction("OK",
  5. new View.OnClickListener() {
  6. @Override
  7. public void onClick(View v) {
  8. //Snackbar上按钮的点击事件
  9. }
  10. }).show();

效果图如下所示:

FloatingActionButton

Floating Action Button表示一个悬浮按钮,一般推荐在一个屏幕上展示一个FloatingActionButton,用于重要的全局操作。

FAB按钮默认会使用主题中定义的背景色,但是我们也可以修改背景色,以下是一些可以设置的属性:

使用起来也很简单,只要在布局文件中配置就可以了:

  1. <android.support.design.widget.FloatingActionButton
  2. android:id="@+id/fab"
  3. android:layout_width="wrap_content"
  4. android:layout_height="wrap_content"
  5. android:layout_margin="20dp"
  6. app:layout_anchor="@id/pager"
  7. app:layout_anchorGravity="bottom|right"
  8. android:clickable="true"
  9. app:rippleColor="#00ff00"
  10. android:src="@drawable/qq"
  11. app:fabSize="normal" />

效果图如下所示:

TabLayout

TabLayout用来实现多Tab分组功能,TabLayout既实现了固定的选项卡(fixed):子Tab View的宽度平均分配,也实现了可滚动的选项卡(scrollable):子Tab View宽度不固定,当子tab过多时,可以横向滚动。

TabLayout有两个比较重要的属性,分别是:

TabLayout一般和Viewpager一起使用,实现联动的多Tab功能(滑动ViewPager,自动切换上面的子Tab)。

下面我们来看一个例子,布局文件如下所示:

  1. <android.support.design.widget.TabLayout
  2. android:id="@+id/tabs"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. app:tabGravity="center"
  6. app:tabMode="fixed"/>
  7. <android.support.v4.view.ViewPager
  8. android:id="@+id/pager"
  9. android:layout_width="match_parent"
  10. android:layout_height="match_parent" />

相应的实现代码如下所示:

  1. ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
  2. TabLayout mTabLayout = (TabLayout) findViewById(R.id.tabs);
  3. //获取ViewPager适配器,views表示ViewPager的选项卡View列表,titleList表示TabLayout中的子Tab标题列表,这里不是重点,代码就不贴了。
  4. MyViewPagerAdapter myViewPagerAdapter = new MyViewPagerAdapter(views, titleList);
  5. mViewPager.setAdapter(myViewPagerAdapter);
  6. //把TabLayout和ViewPager关联起来了
  7. mTabLayout.setupWithViewPager(mViewPager);
  8. //ViewPager适配器
  9. class MyViewPagerAdapter extends PagerAdapter {
  10. private List<View> mListViews;//
  11. private List<String> mTitleList;//TabLayout中的子Tab标题
  12. public MyViewPagerAdapter(List<View> mListViews, List<String> titleList) {
  13. this.mListViews = mListViews;
  14. this.mTitleList = titleList;
  15. }
  16. @Override
  17. public void destroyItem(ViewGroup container, int position, Object object) {
  18. container.removeView(mListViews.get(position));
  19. }
  20. @Override
  21. public Object instantiateItem(ViewGroup container, int position) {
  22. container.addView(mListViews.get(position));
  23. return mListViews.get(position);
  24. }
  25. @Override
  26. public int getCount() {
  27. return mListViews.size();
  28. }
  29. @Override
  30. public boolean isViewFromObject(View arg0, Object arg1){
  31. return arg0 == arg1;//标准写法...
  32. }
  33. @Override
  34. public CharSequence getPageTitle(int position) {
  35. //获取TabLayout中的子Tab标题
  36. return mTitleList.get(position);
  37. }
  38. }

具体效果可以参见CoordinatorLayout中的效果图(都使用了这种关联滚动)。

CoordinatorLayout

CoordinatorLayout是FrameLayout的增强型,主要用来作为顶层布局,协调子View之间的滑动事件处理,以及实现子View之间的状态变化监听。

CoordinatorLayout的子View可以设置layout_anchorlayout_anchorGravity属性,用于将某个子View悬浮于指定View指定位置。

这里我们先看一下CoordinatorLayout结合其他Design组件,一起实现的一些效果,然后用另一篇文章分析下CoordinatorLayout的实现原理。

与AppBarLayout结合

AppBarLayout是一个垂直方向的LinearLayout,通常作为CoordinatorLayout的直接子View使用,AppBarLayout的子View需要设置app:layout_scrollFlags属性,该属性用来控制子View跟随滚动列表一起滚动,还是固定在最上面,有以下几种取值:

Tips:所有设置scroll标志的子View必须在没有设置的之前定义,这样可以确保那些设置过的子View都从上面滚动出屏幕,只留下那些固定的子View在下面。

下面我们来看一个例子,布局文件如下所示:

  1. <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:app="http://schemas.android.com/apk/res-auto"
  3. android:id="@+id/main_content"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:fitsSystemWindows="true"
  7. android:orientation="vertical">
  8. <android.support.design.widget.AppBarLayout
  9. android:id="@+id/appbar"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"
  12. android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
  13. <android.support.v7.widget.Toolbar
  14. android:id="@+id/toolbar"
  15. android:layout_width="match_parent"
  16. android:layout_height="?attr/actionBarSize"
  17. android:background="?attr/colorPrimary"
  18. app:layout_scrollFlags="scroll|enterAlways"
  19. app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
  20. <android.support.design.widget.TabLayout
  21. android:id="@+id/tabs"
  22. android:layout_width="match_parent"
  23. android:layout_height="wrap_content" />
  24. </android.support.design.widget.AppBarLayout>
  25. <android.support.v4.view.ViewPager
  26. android:id="@+id/pager"
  27. android:layout_width="match_parent"
  28. android:layout_height="match_parent"
  29. app:layout_behavior="@string/appbar_scrolling_view_behavior" />
  30. <android.support.design.widget.FloatingActionButton
  31. android:id="@+id/fab"
  32. android:layout_width="wrap_content"
  33. android:layout_height="wrap_content"
  34. android:layout_margin="20dp"
  35. android:clickable="true"
  36. android:src="@drawable/qq"
  37. app:fabSize="normal"
  38. app:layout_anchor="@id/pager"
  39. app:layout_anchorGravity="bottom|right"
  40. app:rippleColor="#00ff00" />
  41. </android.support.design.widget.CoordinatorLayout>

这里使用上面介绍的方式把TabLayout和ViewPager关联起来,代码中ViewPager的子View分别是RecyclerView和NestedScrollView,都可以实现滚动操作,所以可以测试ViewPager的上下滚动行为是怎么影响兄弟节点AppBarLayout的。

上面看到,我们对ViewPager设置了app:layout_behavior="@string/appbar_scrolling_view_behavior",该behavior的实现类是android.support.design.widget.AppBarLayout$ScrollingViewBehavior。而实际上AppBarLayout也拥有一个behavior(通过注解实现的),实现类是android.support.design.widget.AppBarLayout$Behavior,CoordinatorLayout正是依赖这两个Behavior,协调子View之间的滑动处理的,这块内容后续会进行详细介绍。

所以,要实现上面的ToolBar跟随滚动列表滚动,需要注意以下几个几点:

  1. CoordinatorLayout为顶级父容器,负责协调子View间的滚动事件。
  2. AppBarLayout的子View中需要协同滚动列表滚动的view需要设置app:layout_scrollFlags属性
  3. 滚动组件需要设置app:layout_behavior属性。

最终的效果图如下所示:

如上所示,向上滚动列表时,会优先把ToolBar滚动出屏幕,然后才是滚动列表内容;而向下滚动时,会优先把TooBar滚动入屏幕,然后才是滚动列表内容。可见滚动列表的滚动操作间接影响了AppBarLayout的滚动行为,而这正是CoordinatorLayout的作用:协调子View之间的滚动事件。

与CollapsingToolbarLayout结合

CollapsingToolbarLayout一般作为AppBarLayout的直接子View,是对Toolbar的进一步封装,目的是实现可折叠的Toolbar。

CollapsingToolbarLayout提供了一些属性,其中有几个比较重要:

此外,CollapsingToolbarLayout的子View还需要设置以下属性:

下面我们来看一个例子,布局文件如下所示:

  1. <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:app="http://schemas.android.com/apk/res-auto"
  3. android:id="@+id/main_content"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:fitsSystemWindows="true"
  7. android:orientation="vertical">
  8. <android.support.design.widget.AppBarLayout
  9. android:id="@+id/appbar"
  10. android:layout_width="match_parent"
  11. android:layout_height="256dp"
  12. android:fitsSystemWindows="true"
  13. android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
  14. <android.support.design.widget.CollapsingToolbarLayout
  15. android:id="@+id/collapsing_toolbar"
  16. android:layout_width="match_parent"
  17. android:layout_height="match_parent"
  18. android:fitsSystemWindows="true"
  19. app:collapsedTitleGravity="left"
  20. app:contentScrim="?attr/colorPrimary"
  21. app:expandedTitleGravity="center"
  22. app:expandedTitleMarginStart="30dp"
  23. app:layout_scrollFlags="scroll|enterAlways|exitUntilCollapsed"
  24. app:statusBarScrim="@drawable/qq"
  25. app:title="CoordinatorLayout">
  26. <ImageView
  27. android:id="@+id/backdrop"
  28. android:layout_width="match_parent"
  29. android:layout_height="match_parent"
  30. android:fitsSystemWindows="true"
  31. android:scaleType="centerCrop"
  32. android:src="@drawable/qzone"
  33. app:layout_collapseMode="pin"
  34. app:layout_collapseParallaxMultiplier="0" />
  35. <android.support.v7.widget.Toolbar
  36. android:id="@+id/toolbar"
  37. android:layout_width="match_parent"
  38. android:layout_height="?attr/actionBarSize"
  39. app:layout_collapseMode="pin"
  40. app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
  41. </android.support.design.widget.CollapsingToolbarLayout>
  42. </android.support.design.widget.AppBarLayout>
  43. <LinearLayout
  44. android:layout_width="match_parent"
  45. android:layout_height="match_parent"
  46. android:orientation="vertical"
  47. app:layout_behavior="@string/appbar_scrolling_view_behavior">
  48. <android.support.design.widget.TabLayout
  49. android:id="@+id/tabs"
  50. android:layout_width="match_parent"
  51. android:layout_height="wrap_content"
  52. app:tabGravity="center"
  53. app:tabMode="fixed" />
  54. <android.support.v4.view.ViewPager
  55. android:id="@+id/pager"
  56. android:layout_width="match_parent"
  57. android:layout_height="match_parent" />
  58. </LinearLayout>
  59. <android.support.design.widget.FloatingActionButton
  60. android:id="@+id/fab"
  61. android:layout_width="wrap_content"
  62. android:layout_height="wrap_content"
  63. android:layout_margin="20dp"
  64. android:clickable="true"
  65. android:src="@drawable/qq"
  66. app:fabSize="normal"
  67. app:layout_anchor="@id/pager"
  68. app:layout_anchorGravity="bottom|right"
  69. app:rippleColor="#00ff00" />
  70. </android.support.design.widget.CoordinatorLayout>

与上面一样,TabLayout和ViewPager关联起来,代码中ViewPager的子View分别是RecyclerView和NestedScrollView,都可以实现滚动操作,这样滚动下面的滚动列表,可以观察到上面CollapsingToolbarLayout的折叠情况。

此外,通过CollapsingToolbarLayout实现折叠效果,需要注意以下两点:

  1. AppBarLayout的高度需要固定
  2. CollapsingToolbarLayout的子View需要设置layout_collapseMode属性

最终的效果图如下所示:


如上所示,向上滚动列表时,会折叠图片,然后把ToolBar固定在屏幕顶部,最后才是滚动列表内容;而向下滚动时,会优先把折叠的图片展开,然后才是滚动列表内容。可见滚动列表的滚动操作间接影响了CollapsingToolbarLayout的滚动行为,而这正是CoordinatorLayout的作用:协调子View之间的滚动事件。

参考文章

  1. 探索新的Android Material Design支持库
  2. Android的材料设计兼容库(Design Support Library)
  3. Android CoordinatorLayout使用
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注