Android 是时候了解一波MD库控件了

htpps://rainmonth.github.io/posts/A180305.html

摘要

本文主要介绍android.support.design.widget包下的一些Material Design控件,很多市场上绚丽的App的实现都是基于这些库的,Android本身为我们封装出来的效果就足够平常使用了,下面我讲分别详细介绍各个MD控件,同时自己会做一些扩展,本文先大体介绍一下各个控件,然后详细介绍CoordinatorLayout控件。

系列文章参考:

[toc]

CoordinatorLayout

使用场景

  • 作为顶层容器;
  • 作为协调子View交互的容器;

注意事项

  • 通过为子View指定Behavior,CoordinatorLayout可以让在同一个父容器的子View之间有许多不同种类的交互(子View之间、子View和父View之间),CoordinatorLayout的子View可以指定默认的Behavior
  • Behavior可以用来实现不同的交互和附加的布局改动效果;
  • 可以通过设置CoordinatorLayout.LayoutParams#setAnchorId(int)来实现浮动相关效果;
  • 可以通过设置`CoordinatorLayout.LayoutParams#insetEdge参数来控制子View插入CoordinatorLayout的方式

AppBarLayout

AppBarLayout继承自LinearLayout,但他实现了很多Material Design中App Bar概念中的功能,其中的代表就是手势滑动。

  • AppBarLayout的子View必需声明其滚动的行为(通过setScrollFlags(int)方法或’app:layout_scrollFlags’属性);
  • AppBarLayout通常是配合CoordinatorLayout来使用的,并且是其直接子View,如果其父类不是CoordinatorLayout,那么其很多特性就发挥不出来;
  • AppBarLayout通常还需要一个同级的滚动控件(即兄弟控件),这样就能知道AppBarLayout需要在什么时机配合滚动了。

layout_scrollFlags属性解释

上面说了,AppBarLayout的子View必须设置layout_scrollFlags属性,否则其很多特性就不能发挥作用了,那么这个属性到底有什么作用呢。这个属性共有以下5种值:

1
2
3
4
5
SCROLL_FLAG_SCROLL,
SCROLL_FLAG_EXIT_UNTIL_COLLAPSED,
SCROLL_FLAG_ENTER_ALWAYS,
SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED,
SCROLL_FLAG_SNAP

下面分别对这五种属性作说明:

  • SCROLL_FLAG_SCROLL,对应于属性scroll,表示伴随着滚动事件滚出或滚进屏幕;

    1. 该值是其他四种值生效的前提,及其他四个值如果要生效,必须设置这个值;
    2. 如果设置了该属性的子View前面有没有设置该属性的统计View,那么AppBarLayout其他设置了改属性的子View都无效
  • SCROLL_FLAG_ENTER_ALWAYS,对应于属性enterAlways,在和scroll一起使用时,当发生向下滚动事件时,设置了该属性的子View会优先于SrollView先进入屏幕;

  • SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED,对应于enterAlwaysCollapsed,是enterAlways的附加值。当子View设置的layout_scrollFlags属性值为scroll|enterAlways|enterAlwaysCollapsed时,如果子View设置了最小高度minHeight,那么当发生向下滚动的事件时,子View会先滚动,知道达到最小高度,达到后,ScrollView会滚动知道滚动完毕,然后子View在滚动剩余的高度。

  • SCROLL_FLAG_EXIT_UNTIL_COLLAPSED,对应于exitUntilCollapsed,同样和最小高度有关,当向上滑动的事件发生时,设置该属性的子View会先向上滚动至最小高度,然后保持高度不变,然后ScrollView再开始滚动。

  • SCROLL_FLAG_SNAP,对应于snap属性,即ChildView的滚动吸附效果,设置了该值后,ChildView不会存在局部显示的情况,要么全部滚进屏幕,要么全部滚出屏幕。

总结下:scroll就是子View后滚,enterAlways就是子View先滚,enterAlwaysCollapsed就是子View先滚到折叠状态然后ScrollView再滚,完成后子View在滚,exitUntilCollapsed,子View滚到到折叠态后就不在滚了,开始管ScrollView,snap指的是吸附滚动,要么全部显示,要么全部隐藏。

最终保留的高度

这个最终保留高度其实是针对layout_scrollFlagsexitUntilCollapsedenterAlwaysCollapsed的,当layout_scrollFlags设置成了上面两个值时,前者在子View滑动达到最小高度后子View就不在滚动,这个就是最终保留高度

android.support.v7.Toolbar

Toolbar为我们顶部导航栏的开发带来了许多便利,但如果使用不注意也会有很多坑。

便利

  • 可以只将Toolbar当做一个容器,它本身就是继承自ViewGroup的,然后在里面定义自己的顶部导航栏布局

  • 在没有ActionBar的AppCompatActivity中,可以通过setSupportActionBar(Toolbar)来设置ActionBar,然后使用ActionBar的一些功能。

    注意:这里必须是没有ActionBar的AppCompatActivity,否则会报如下错误:

    1
    Caused by: java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.

Toolbar元素间距调整麻烦

直接使用Toolbar或由它初始化的ActionBar时,UI上的定制性比较差,Toolbar主要包含以下几个元素(按从左到右的顺序):

  1. NavigationIcon,导航图标,默认为向左箭头,可以自己设置;
  2. Logo,当前页面对应的Logo,国内很少使用这个属性;
  3. 标题,有两种标题
    1. Title,页面标题,常用;
    2. SubTitle,页面子标题,较常用;
  4. Menu,页面右边对应的菜单;

说UI的定制,主要就是前面1、2、3三个元素之间的间距调整,在V22之前,由于不存在contentInsetStartWithNavigation属性,1和3的间距还可以接受,但V22之后,添加了这个属性,会发现1和3的间距太大了,解决方法就是设置给属性的值为0dp,设置完成后发现NavigationIcon与Title的距离还是太大了,这是因为NavigationIcon是存在padding值得,那么如何搞定这个padding值呢,我们可以通过AppTheme的如下属性来设置:

<item name="toolbarNavigationButtonStyle">@style/myToolbarNavigationButtonStyle</item>

其中myToolbarNavigationButtonStyle定义如下:

1
2
3
4
5
<style name="myToolbarNavigationButtonStyle" parent="@style/Widget.AppCompat.Toolbar.Button.Navigation">
<item name="android:minWidth">32dp</item>
<item name="android:padding">0dp</item>
<item name="android:scaleType">centerInside</item>
</style>

通过上面的padding可以实现NavigationIcon相关的属性定制。

ActionBar方法调用存在限制

一定要先调用setSupportActionBar这个方法之后然后在调用ActionBar的相关方法

CardView