一个Activity掌握Design新控件

一个Activity掌握Design新控件


欢迎转载,转载请注明原文地址:http://blog.csdn.net/lavor_zl/article/details/51295364谢谢。

谷歌在推出Android5.0的同时推出了全新的设计Material Design,谷歌为了给我们提供更加规范的MD设计风格的控件,在2015年IO大会上推出了Design支持包,Design常用的新控件有下面8种。

1. TextInputLayout(文本输入布局)


TextInputLayout的作用是将EditText包裹起来,使得EditText的android:hint属性的值以浮动标签的形式显示出来,同时可以通过setErrorEnabled(boolean)setError(CharSequence)来显示错误信息。

在xml文件中定义TextInputLayout:

    <android.support.design.widget.TextInputLayout
        android:id="@+id/text_input_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:hint="作者"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </android.support.design.widget.TextInputLayout>

在java文件中设置错误信息:

        this.textinputlayout.setErrorEnabled(true);
        this.textinputlayout.setError("作者不能包含标点符号");

2. TabLayout(选项卡布局)


Tablayout提供横向布局显示选项卡,它取代了ActionBar添加选项卡的方式。它经常与ViewPager配合使用。

在xml文件中定义TabLayout:

        <android.support.design.widget.TabLayout
                 android:id="@+id/tab_layout"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content">
        </android.support.design.widget.TabLayout>  

在java文件中添加选项卡:

        tablayout.addTab(tablayout.newTab().setText("Tab1"));
        tablayout.addTab(tablayout.newTab().setText("Tab2"));
        tablayout.addTab(tablayout.newTab().setText("Tab3"));

Tablayout与ViewPager配合使用:

  • tablayout.setupWithViewPager();
    这种方法下面选项卡的标题由ViewPager决定
  • viewPager.addOnPageChangeListener(new TabLayoutOnPageChangeListener(tablayout));
    这种方法下面选项卡的标题由Tablayout决定

3. Snackbar


Snackbar提供比Toast轻量级的反馈操作,谷歌推荐使用Snackbar替代Toast。Snackbar显示或者消失的时候有一个回调方法。

        //tablayout是Snackbar努力找到持有自己的视图
        Snackbar snackbar=Snackbar.make(tablayout,"我是Snackbar",Snackbar.LENGTH_LONG);
        //为snackbar设置回调方法
        snackbar.setCallback(new Snackbar.Callback() {
            @Override
            public void onDismissed(Snackbar snackbar, int event) {
                super.onDismissed(snackbar, event);
                Log.i("Snackbar","Snackbar消失了");
            }
            @Override
            public void onShown(Snackbar snackbar) {
                super.onShown(snackbar);
                Log.i("Snackbar","Snackbar出现了");
            }
        });
        //显示snackbar
        snackbar.show();  

4. FloatingActionButton(浮动按钮)


FloatingActionButton在用户界面中通常是一个漂浮的小圆圈,它有自身独特的动态效果,比如变形、弹出、位移等等。

FloatingActionButton默认的背景颜色是主题的colorAccent,还可以通过app:backgroundTint来修改,也可以通过android:backgroundTint属性修改,但是android:backgroundTint属性只能在API21及以上使用。

FloatingActionButton的定义很简单:


            <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab_add_task"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_add_circle_pink_400_18dp"
                app:backgroundTint="@color/blue"
                app:fabSize="normal" />  

5. NavigationView(导航视图)


NavigationView顾名思义是导航视图,一般与DrawerLayout(抽屉布局)联合使用。它为应用程序提供标准的导航菜单,菜单内容可以通过一个xml菜单文件来填充。

在xml文件中定义NavigationView


            <android.support.design.widget.NavigationView
            android:id="@+id/navigation_menu"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:fitsSystemWindows="true"
            app:headerLayout="@layout/drawer_navigation_header"
            app:menu="@menu/drawer_navigation_menu"
            />  
  • <code>app:headerLayout</code>:表示NavigationView的头部布局
  • <code>app:menu</code>:表示NavigationView的导航菜单

头部布局很简单就是一个普通的布局文件,我们来看看导航菜单的定义吧。


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/drawer_home"
            android:icon="@drawable/ic_home_black_24dp"
            android:title="@string/home" />
        <item
            android:id="@+id/section"
            android:icon="@drawable/ic_more_horiz_black_24dp"
            android:title="分组1">
            <menu>
                <item
                    android:id="@+id/drawer_favourite"
                    android:icon="@drawable/ic_favorite_black_24dp"
                    android:title="@string/favourite" />
                <item
                    android:id="@+id/drawer_downloaded"
                    android:icon="@drawable/ic_file_download_black_24dp"
                    android:title="@string/downloaded" />
            </menu>
        </item>
        <item
            android:id="@+id/section2"
            android:title="分组2">
            <menu>
                <item
                    android:id="@+id/drawer_more"
                    android:icon="@drawable/ic_more_horiz_black_24dp"
                    android:title="@string/more" />
                <item
                    android:id="@+id/drawer_settings"
                    android:icon="@drawable/ic_settings_black_24dp"
                    android:title="@string/settings" />
            </menu>
        </item>
    </group>
</menu>  

我们来分析一下该xml文件:
<code>group</code>:表示组
<code>android:checkableBehavior</code>:可以接受下面3种值

  • <code>single</code> 组中只有一个菜单项可以checked
  • <code>all</code> 组中所有菜单项可checked
  • <code>none</code> 组中所有菜单项都不可checked

<code>item</code>:表示项,下面可以有子菜单, <code>item</code>与<code>item</code>会默认有分割线分开。

6. AppBarLayout(应用程序栏布局)


AppBarLayout是一个垂直的线性布局,实现了Material Design概念的应用程序栏,支持滚动手势。
它的子视图提供所需的滚动行为:

  • 在java文件中通过setScrollflags(int)设置
  • 在xml布局文件中通过````

AppBarLayout经常作为CoordinatorLayout的直接子视图使用。
AppBarLayout的作用是把AppBarLayout包裹的内容都作为应用程序栏。

我们在xml文件中定义一个AppBarLayout,AppBarLayout下面有一个Toolbar和一个TabLayout


         <android.support.design.widget.AppBarLayout
            android:id="@+id/app_bar_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                app:layout_scrollFlags="scroll|enterAlways"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="?attr/colorPrimary"
                android:fitsSystemWindows="true"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
            </android.support.v7.widget.Toolbar>
            <android.support.design.widget.TabLayout
                android:id="@+id/tab_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            </android.support.design.widget.TabLayout>
        </android.support.design.widget.AppBarLayout>  

我们向上滑动AppBarLayout看看有什么效果

此时我们发现Toolbar被隐藏了,我们再在向下滑动AppBarLayout,发现Toolbar又出来了。
这就相当于是一个可以折叠的工具栏。

这是因为Toolbar设置了app:layout_scrollFlags="scroll|enterAlways"
app:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样这个view才会滚动出屏幕,否则它将一直固定在顶部。可以使用的其他flag有:

  • enterAlways: 一旦向下滚动,不管是否继续滚动,该view都会变为可见。
  • enterAlwaysCollapsed: 这个属性是作为enterAlways属性的附加属性使用的,这个flag定义的是何时进入,,当你定义了一个minHeight,并且定义了enterAlways属性,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
  • exitUntilCollapsed: 这个flag时定义何时退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候开始慢慢消失。

app:layout_scrollFlags这个属性其实一般就只有下面4种使用情况,我们来一一讲解。


1. app:layout_scrollFlags="scroll"

  • 该view显示时,只有在滚动视图顶部向上滚动时,该view才会慢慢消失。
  • 该view消失后,只有在滚动视图顶部向下滚动时,该view才会慢慢出现。

2. app:layout_scrollFlags="scroll|enterAlways"

  • 该view显示时,只要滚动视图向上滚动,该view就会慢慢消失。
  • 该view消失后,只要滚动视图向下滚动,该view就会慢慢出现。

3. app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed",同时该view设置了minHeight

  • 该view显示时,只要滚动视图向上滚动,该view就会慢慢消失。
  • 该view消失后,只要滚动视图向下滚动,该view就会慢慢出现:
    • 当滚动视图不在顶部时,该view只会慢慢出现minHeight高度的内容
    • 当滚动视图在顶部时,该view会慢慢出现全部的内容

4. app:layout_scrollFlags="scroll|exitUntilCollapsed",同时该view设置了minHeight

  • 该view显示时,只有在滚动视图顶部向上滚动时,该view才会慢慢消失,但不会完全消失,会保留着 minHeight高度的内容依然可见。
  • 该view消失后,只有在滚动视图顶部向下滚动时,该view才会慢慢出现。

注意:只有AppBarLayout第一个设置app:layout_scrollFlags属性的直接子视图可以折叠

7. CoordinatorLayout(协作布局)


CoordinatorLayout是一个超级强大的FrameLayout。
CoordinatorLayout有两个主要用途:

  • 作为顶级应用程序的装饰或着色布局
  • 作为特定交互的容器,与一个或多个孩子视图交互

CoordinatorLayout作为一个父视图,它的孩子可以通过特定的行为与CoordinatorLayout别的孩子交互。
当视图类作为CoordinatorLayout的孩子时,可以定义特定的行为。

  • 在xml文件中使用app:layout_behavior
  • 在view类使用@DefaultBehavior修饰符来添加注解。

在CoordinatorLayout的孩子视图FloatingActionButton中设置
app:layout_behavior="com.lavor.designnewcontrols.ScrollBehavior"
com.lavor.designnewcontrols.ScrollBehavior的代码如下:


public class ScrollBehavior extends CoordinatorLayout.Behavior<View> {
    /**
     * 因为是在XML中使用app:layout_behavior定义静态的这种行为,
     * 必须实现一个构造函数使布局的效果能够正常工作。
     * 否则 Could not inflate Behavior subclass error messages.
     */
    public ScrollBehavior(Context context, AttributeSet attrs) {
        super();
    }

    /**
     * 开始滚动时
     */
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
        //如果child可见,设置其不可见
        if(child.getVisibility()==View.VISIBLE){
            ((FloatingActionButton)child).hide();
        }
        //如果child不可见,设置其可见
        else{
            ((FloatingActionButton)child).show();
        }
        return super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
    }
}  

CoordinatorLayout的子视图可以设置app:layout_anchor属性,该属性的值对应着CoordinatorLayout中其它子视图(不能是该视图本身或其子视图)的android:id属性。这可以将浮动视图放在任意地方。


                <android.support.design.widget.FloatingActionButton
                android:id="@+id/fab_add_task"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_add_circle_pink_400_18dp"
                app:fabSize="normal"
                app:layout_anchor="@id/toolbar"
                app:layout_anchorGravity="bottom|right|end" />  

我们将FloatingActionButton(浮动按钮)放置到Toolbar的右下方结束位置。

注意:使用CoordinatorLayout时,AppBarLayout下面有一个RecyclerView时,RecyclerView会与AppBarLayout重叠,因为CoordinatorLayout是帧布局。

要解决这个问题可以设置RecyclerView的app:layout_behavior="@string/appbar_scrolling_view_behavior",其实此时该属性的值就是android.support.design.widget.AppBarLayout$ScrollingViewBehavior

8. CollapsingToolbarLayout(折叠工具栏布局)


CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承至FrameLayout,它通常是作为AppBarLayout直接子视图使用。它提供的折叠工具栏更高级,还可以制造视觉差。

对于CollapsingToolbarLayout,我们通常是这样使用的,将其定义为AppBarLayout的第一个直接子视图,并且其自身定义如下:它里面有一个ImageView和一个Toolbar,形成折叠工具栏。


            <android.support.design.widget.CollapsingToolbarLayout
                    app:layout_scrollFlags="scroll|exitUntilCollapsed"
                    app:contentScrim="?attr/colorPrimary"
                    app:expandedTitleMarginStart="48dp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">
                    <ImageView
                    android:src="@drawable/bg"
                    android:scaleType="centerCrop"
                    app:layout_collapseMode="parallax"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />
                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="60dp"
                    app:layout_collapseMode="pin"
                    android:background="?attr/colorPrimary"
                    android:fitsSystemWindows="true">
                </android.support.v7.widget.Toolbar>
            </android.support.design.widget.CollapsingToolbarLayout>
  • 首先,CollapsingToolbarLayout要设置app:layout_scrollFlags,这个属性在介绍AppBarLayout的时候已经讲过了,app:contentScrim表示滚动达到一定阈值后Toolbar的背景颜色,app:expandedTitleMarginStart设置扩张时候(还没有收缩时)title向左填充的距离。
  • 其次, ImageView的app:layout_collapseMode属性的值为parallax,设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,通常和app:layout_collapseParallaxMultiplier属性(设置视差因子)搭配使用,其值为0~1。
  • 最后,Toolbar的app:layout_collapseMode属性的值为pin,设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。

程序源代码下载:一个Activity掌握Design新控件

关于Design新控件国外有一篇不错的教程:https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout
该教程源代码的github地址:https://github.com/chrisbanes/cheesesquare

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容