Meterial Design最佳体验(1): 使用Toolbar, CoordinatorLayout, AppBarLayout等实现精美标题栏

    xiaoxiao2021-03-25  32

                          Meterial Design最佳体验(1):

    使用Toolbar, CoordinatorLayout, AppBarLayout等实现精美标题栏

     

       作者:

      蒋东国

       时间:

      2017年03月10日 星期五        

       应用来源:

       路痴宝v1.2 (三星C9 Pro)

      博客地址:

       http://blog.csdn.net/andrexpert/article/details/61236581                                            

          

           情景再现“Material Design是Google在2014年的I/O大会提出的一套全新的界面设计语言,它包含了视觉、运动、互动效果等特性,其宗旨就是解决Android平台界面风格不统一的问题。虽然Material Design是一套界面设计语言,但为了方便APP开发,Google提供了一个Design Support库,这个库对一些常见的控件和效果进行了封装,使开发工程师在在不了解Material Design的情况下能够将自己的应用Material化。”

           Material Design特有的设计风格和理念,它给人以精致的美观和良好的体验。自Android 5.0推出以后,不仅谷歌将所有的系统APP使用Material Design风格,软件市场上越来越多的APP也Material化,可见Material Design风格将是未来Android APP追求良好体验的必然趋势。为了使我们的APP也能够Material化,Google官方给出了几点建议:

    (1)   遵从Material Design设计原则,部署平台高于Android 5.0;

    (2)   使用Material主题;

    (3)   使用Desugn Support库等Material风格组件,比如RecyclerView、CardView等;

    (4)   使用自定义的shadows和animation……等等。

    当然,在学习Material Design之前,我们从最新版QQ(v6.6.9)和摩拜单车借用几张图来感受一样Material Design风格所带来的魅力-侧滑菜单、侵入式带可收缩标题栏。

                                   

            好了,在了解Material Design是什么东西之后,接下来就应该上干货了。今天主要讲解如何使用Toolbar、AppBarLayout、Coordinater、CollapsingToolbarLayout控件实现一个如摩拜单车样的侵入式带可折叠效果的标题栏,它们分别出自于SDK自带的库appcompat-v7-24.2.1、design-24.2.1。对于Android Studio开发环境来说,我们只需在buid.gradle文件的依赖中添加如下代码:

    compile'com.android.support:appcompat-v7:24.+' compile'com.android.support:design:24.2.1'

    1.  创建自定义Material主题

         由于新建的Android项目项目会指定一个默认的主题,这个主题是不具备Material效果而且带默认ActionBar。为此,我们需要使用Material提供的不带ActionBar的主题替换默认主题,新的Material主题会给我们带来诸如Activity切换动画,为系统组件渲染指定颜色、添加系统组件操作动画等效果。

    (1)   /res/values/style.xml:创建自定义Material风格主题App,它继承于Support-v7库中定义的Material风格theme,具体代码如下:

    <resources> <!-- application materialdesign theme. --> <style name="CustomAppTheme"parent="android:Theme.Material.Light.NoActionBar"> <!—以下属性定义(颜色调色板)--> <item name=" android: colorPrimary">@color/colorPrimary</item> <item name="android:colorPrimaryDark">@color/colorPrimaryDark</item> <item name="android:colorAccent">@color/colorAccent</item> <item name="android:textColorPrimary">@color/textColorPrimary</item> <item name="android:windowBackground">@color/windowBackground</item> <item name="android:navigationBarColor">@color/navigationBarColor</item> </style> </resources>

           其中,colorPrimary用于指定标题栏背景颜色;colorPrimaryDark属性用于指定状态栏背景颜色;colorAccent指定诸如chexkboxes、text点击效果;textColorPrimary属性用于指定标题栏标题字体颜色;windowBackground属性指定内容区背景颜色;navigationBarColor属性指定导航栏背景颜色….(详见sdk/docs/preview/material/theme.html)。当然,还有很多属性未列举,可以根据自身需求进行深度定制。需要注意的是,Support-v7库提供的系列Material主题必须在minSdkVersion大于5.0 (API21)基础上使用。当然,我们也可以让CustomAppTheme继承于"Theme.AppCompat.Light.NoActionBar",上述定制的颜色风格仍然有效。

    (2)   AndroidManifest.xml:使用自定义Material风格主题

    <application android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:theme="@style/ CustomAppTheme "> ……. </application>

    2.  自定隐藏式标题栏实现

        看下运行效果:

        

         那么,我们就来详细了解下Toolbar、AppBarLayout、CoordinatorLayout在这里面都扮演了些什么样的角色。

    (1)  android.support.v7.widget.Toolbar

    Toolbar是android-support-v7库提供的一个具有Material特性的控件,它不仅继承了ActionBar的所有功能,并且与ActionBar只能固定在顶部不同的是,Toolbar可以随便移动,并且可以同其他控件实现一些Material Design效果。简单介绍了Toolbar控件后,接下来就是如何去使用Toolbar作为Activity的标题栏。首先,activity_main.xml文件中添加Toolbar控件:

    <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"> <android.support.v7.widget.Toolbar android:id="@+id/main_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="@color/colorPrimary" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" /> </ FrameLayout>

           其中,android:layout_height="?attr/actionBarSize"属性指定Toolbar标题栏的高度;android:theme用于指定Toolbar上元素的主题风格,这里使用Dark深色风格目的是与Toolbar主题的Light浅色风格区分开来;app:popupTheme属性用于指定弹出菜单项的主题风格。然后,我们就可以在MainActivity中使用定义的Toolbar,具体代码如下:

    Toolbar mToolbar = (Toolbar)findViewById(R.id.main_toolbar); //设置Activity的标题栏ActionBar为Toolbar setSupportActionBar(mToolbar); //使能Home键 ActionBaractionBar = getSupportActionBar(); if(actionBar!= null){ actionBar.setDisplayHomeAsUpEnabled(true); actionBar.setHomeButtonEnabled(true); }

    当然,我们也可以像系统自带的ActionBar样为标题栏添加菜单项,即在res/menu目录下创建menu_toolbar.xml,并使用app:showAsAction属性来指定每个item按钮显示的位置。其中,always表示永远显示在标题栏上;ifRoom表示按钮在空间足够时显示在标题栏上,否则隐藏到菜单栏中;never表示永远隐藏在菜单栏中。具体配置代码如下:

    <?xmlversion="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <itemandroid:id="@+id/menu_personal" android:title="个人主页" android:icon="@drawable/ic_personal" app:showAsAction="always"/> <itemandroid:id="@+id/menu_clear" android:title="清空" android:icon="@drawable/ic_clear" app:showAsAction="ifRoom"/> <itemandroid:id="@+id/menu_more" android:title="更多" android:icon="@drawable/ic_more" app:showAsAction="never"/> </menu>

    (2)  android.support.design.widget.CoordinatorLayout

          经过步骤(1),我们已经成功地将系统自带的ActionBar替换成Toolbar,但是如果仅仅是做个替换那就太没意义了。既然要实现一个Material化的标题栏,那么就应该尽量使用具有Material特性的控件。非常明显,FramLayout就是“开刀”的对象,我们使用support-design库中的CoordinatorLayout来替换。CoordinatorLayout可以说是一个加强版的FrameLayout,在普通情况下它的功能与FrameLayout一致。由于CoordinatorLayout控件由Design Support库提供,自然具有Material Design风格特性,并且它还能够能够监听其所有子控件的各种事件,然后自动根据当前布局情况作出合理的响应。为了体现CoordinatorLayout的强大,这里使用Support-design库提供的FloatingActionButton、Snackbar控件来进行演示。其中,Snackbar类似于Toast,但是它允许在提示用户的基础上添加一个可交互按钮;FloatingActionButton是一种悬浮按钮,它默认使用CustomAppTheme主题中定义的colorAccent来作为按钮的颜色。

    <?xml version="1.0"encoding="utf-8"?> <android.support.design.widget.CoordinatorLayoutxmlns: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.v7.widget.Toolbar android:id="@+id/main_toolbar" ……/> <android.support.design.widget.FloatingActionButton android:id="@+id/main_delete_float_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_marginBottom="13dp" android:layout_marginRight="13dp" android:scaleType="centerCrop" android:src="@drawable/ic_choose" app:elevation="10dp" /> </android.support.design.widget.CoordinatorLayout>

           其中,app:elevation="10dp"属性用于设置FloatingActionButton控件高度,高度值越大,投影范围也就越大。我们使当点击悬浮按钮时,弹出一个Snackbar提示,使用CoordinatorLayout前后效果如下图(a)、(b)所示。由图(a)可知,Snackbar提示条将悬浮菜单覆盖住了,这是由于FrameLayout的布局特性所决定的;而对于图(b)可知,当弹出Snackbar时, FloatingActionButton自动向上移动距离布局边缘的同等距离,这是因为CoordinatorLayout能够自动根据当前布局情况对所有子控件作出合理的响应。MainActivity中相关代码:

    FloatingActionButton mBtnDeleteData =(FloatingActionButton) findViewById(R.id.main_delete_float_btn); mBtnDeleteData.setOnClickListener(newView.OnClickListener() { @Override public voidonClick(View view) { Snackbar.make(view, "删除数据", Snackbar.LENGTH_SHORT).setAction("取消", new View.OnClickListener() { @Override public void onClick(View v) { } }).show(); } });

                          

    (3) android.support.design.widget.AppBarLayout

          到这里,一个精致Material风格的标题栏看似已经实现了,那么,接下来我们就向Activity的内容区填充数据吧。我们使用RecyclerView和CardView来枚举内部存储器所有视频列表,由于篇幅原因具体实现就在下一篇博文中介绍。从图(a)的效果来看,视频列表完全把标题栏覆盖了,这是由于CoordinatorLayout本身就是FrameLayout的强化版,FrameLayout在不进行明确定位的情况下默认都会摆放在布局的左上角。为了解决这个问题,我们使用Support-design库中提供的AppBarLayout来解决。AppBarLayout实际上是一个垂直方向的LinearLayout,它在内部做了很多滚动时间的封装,并应用了一些Material Design设计理念。使用方法如下:

    <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.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <!—Toolbar添加app: layout_scrollFlags --> <android.support.v7.widget.Toolbar ….. app:layout_scrollFlags="scroll|snap|enterAlways" …../> </android.support.design.widget.AppBarLayout> <!—RecyclerView添加app:layout_behavior --> <android.support.v7.widget.RecyclerView android:id="@+id/main_pic_list" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> <android.support.design.widget.FloatingActionButton android:id="@+id/main_delete_float_btn" ….. /> </android.support.design.widget.CoordinatorLayout>

           我们定义一个AppBarLayout,将Toolbar放置在AppBarLayout中,就可以解决Toolbar被RecyclerView遮挡的问题。但是,还不能够使Toolbar跟随RecyclerView滚动而变化。事实上,当为RecyclerView添加app:layout_behavior="@string/appbar_scrolling_view_behavior"属性后,RecyclerView滚动的时候就已经将滚动事件都通知了AppBarLayout,只是我们还没有进行处理而已,这里就需要为Toolbart添加app: layout_scrollFlags属性,该属性用于实现当AppBarLayout接收到RecyclerView的滚动事件后,它内部的子控件如何对这些事件作出相应的反应。其中,scroll表示当RecyclerView向上滚动时,Toolbar会跟着一起向上滚动并隐藏;enterAlways表示当RecyclerView向下滚动时,Toolbar会跟着一起向下滚动并显示;snap表示当Toolbar还没有完全隐藏或者显示时,会根据当前滚动的距离,自动选择是隐藏还是显示。

                 

    3.     可折叠式标题栏实现

    运行效果演示:

    使用Toolbar实现的标题栏看上去和传统的ActionBar区别不大,只不过Toolbar可以相应RecyclerView的滚动事件进行隐藏和显示。为了实现可折叠的标题栏,这里使用support-design库提供的CollapsingToolbarLayout控件。CollapsingToolbarLayout是一个作用在Toolbar基础之上的布局,它不仅能够展示一个标题,而且可以让Toolbar效果变得更加的丰富。需要注意的是,CollapsingToolbarLayout是不能单独使用的,它在设计时只能作为AppBarLayout的直接子布局来使用,而AppBarLayout又必须是CoordinatorLayout的子布局。

    (1) 可折叠标题栏界面代码

    <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.design.widget.AppBarLayout android:id="@+id/personal_info_appBar" android:layout_width="match_parent" android:layout_height="250dp"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/personal_info_collapsingbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:contentScrim="@color/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/personal_info_bar_background" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="fitXY" app:layout_collapseMode="parallax" /> <android.support.v7.widget.Toolbar android:id="@+id/personal_info_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>

           其中,AppBarLayout标签中使用android:layout_height="250dp"用于设定标题栏可扩展的高度;CollapsingToolbarLayout标签中使用app:contentScrim属性用于指定CollapsingToolbarLayout在趋于折叠状态以及之后的背景颜色、app:layout_scrollFlags属性用于指定接收到NestedScrollView传递的滚动事件后作出何种相应,其中,scoll表示CollapsingToolbarLayout会随着NestedScrollView的滚动一起滚动,exitUntilCollapsed表示当CollapsingToolbarLayout随着滚动完成折叠之后就保留在界面上,不再移除屏幕;ImageView标签即为可折叠标签栏的背景图片,Toolbar标签就是折叠以后的标题栏了,它们都使用了同一个属性-app:layout_collapseMode,该属性用于指定当前控件在CollapsingToolbarLayout控件折叠过程中的折叠模式,其中Toolbar指定成pin,表示在折叠的过程中位置始终保持不便,ImageView指定成parallax,表示在折叠的过程中产生一定的错位偏移。

    (2) 内容详情界面代码

          内容详情界面最外布局使用了一个NestedScrollView,它是和AppBarLayout平级的并同属于CoordinatorLayout 的子控件。NestedScrollView是ScrollView的扩展,它不仅允许使用滚动的方式来查看屏幕以外的数据,并且还增加了嵌套响应滚动事件的功能。由于CoordinatorLayout 本身已经可以响应滚动事件了,因此我们在它的内部就需要使用NestedScrollView或RecyclerView来生成滚动事件,通过app:layout_behavior属性来指定一个布局行为,这里指定的是appbar来执行响应NestedScrollView产生的滚动事件。

    <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="15dp" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:layout_marginTop="35dp" app:cardCornerRadius="4dp"> <TextView android:id="@+id/personal_info_detail_tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="16sp" android:layout_margin="7dp" /> </android.support.v7.widget.CardView> </LinearLayout> </android.support.v4.widget.NestedScrollView> (3) 悬浮按钮

          通过运行效果gif图可知,在标题栏的右下角会有一个悬浮按钮,用于跳转到路痴宝的下载界面。FloatingActionButton也和AppBarLayout、NestedScrollView平级的并同属于CoordinatorLayout 的子控件。FloatingActionButton中使用app:layout_anchor属性指定了一个锚点,我们将锚点设置为AppBarLayout的ID,这样悬浮按钮就会出现在标题栏的区域内;使用app:layout_anchorGravity属性将悬浮按钮定位在标题栏区域的右小角。

    <!--悬浮在标题栏的按钮--> <android.support.design.widget.FloatingActionButton android:id="@+id/personal_info_float_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:src="@mipmap/download" app:layout_anchor="@id/personal_info_appBar" app:layout_anchorGravity="bottom|end" />

    码字不易,转载请声明出处:http://blog.csdn.net/andrexpert/article/details/61236581

    最后的话:“本文对Material Design进行了简单的介绍,并详细阐述了support-v7、support-design库中CoordinatorLayout、AppBarLayout、Toolbar、CollapsingToolbarLayout、 NestedScrollView、FloatingActionButton等Material风格控件的特性和使用方法。由于篇幅不能太长,文中提及的RecyclerView、CardView、视频缩略图的获取等相关和Demo将再“Material Design最佳体验(2):使用RecyclerView、CardView、SwipeRefreshLayout实现下拉刷新列表中给出。" 关于Demo:第三部分Demo-可折叠式标题栏实现Demo

    转载请注明原文地址: https://ju.6miu.com/read-26040.html

    最新回复(0)