Android Design Support Library
来源:互联网 发布:英文写作润色软件 编辑:程序博客网 时间:2024/06/11 00:55
Google在2015的IO大会上,给我们带来了更加详细的Material Design设计规范,同时,也给我们带来了全新的Android Design Support Library,在这个support库里面,Google给我们提供了更加规范的MD设计风格的控件。最重要的是,Android Design Support Library的兼容性更广,直接可以向下兼容到Android 2.2。
使用Support Library非常简单,添加引用即可:
compile 'com.android.support:design:23.2.0' //可修改版本号为自己匹配
Design Support Library包含8个控件,具体如下:
下面分别详细介绍。
介绍这几个控件之前,我们先来看看Material Design主题的风格。
MD的Theme
md的主题有:
- @android:style/Theme.Material (dark version)
- @android:style/Theme.Material.Light (light version)
- @android:style/Theme.Material.Light.DarkActionBar
与之对应的Compat Theme:
- Theme.AppCompat
- Theme.AppCompat.Light
- Theme.AppCompat.Light.DarkActionBar
我们可以根据我们的app的风格,去定制Color Palette(调色板),重点有以下几个属性:
<resources> <!-- Base application theme. --> <style name="AppBaseTheme" parent="Theme.AppCompat"> <!-- customize the color palette --> <item name="colorPrimary">@color/material_blue_500</item> <item name="colorPrimaryDark">@color/material_blue_700</item> <item name="colorAccent">@color/material_green_A200</item> </style></resources>
colorPrimary 对应ActionBar的颜色。
colorPrimaryDark对应状态栏的颜色
colorAccent 对应EditText编辑时、RadioButton选中、CheckBox等选中时的颜色。
注:对于5.0以下的设备,目前colorPrimaryDark无法去个性化状态栏的颜色;底部的navagationBar可能也不一样,更别说设置颜色了。
Snackbar
Snackbar提供了一个介于Toast和AlertDialog之间轻量级控件,它可以很方便的提供消息的提示和动作反馈。Snackbar和Toast比较相似,但是用途更加广泛,并且它是可以和用户进行交互的。Snackbar使用一个动画效果从屏幕的底部弹出来,过一段时间后也会自动消失。
Snackbar.make(snackBar, "Snackbar comes out", Snackbar.LENGTH_LONG) .setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText( MainActivity.this,"Toast comes out",Toast.LENGTH_SHORT).show(); } }).show();
这里调用Snackbar的make()方法来创建一个Snackbar对象,make()方法的第一个参数是Snackbar显示的基准元素,需要传入一个view,只要是当前界面布局的任意一个view都可以,Snackbar会使用这个view来自动查找最外层的布局,用于展示Snackbar。第二个参数就是Snackbar中显示的内容,第三个参数是Snackbar显示的时长。这些和Toast都是类似的。
接着这里又调用了一个setAction()方法来设置一个动作,从而让Snackbar不仅仅是一个提示,而是可以和用户进行交互的,这里Action可以设置多个。最后调用show()方法让Snackbar显示出来。
现在重新运行一下程序,效果如下图所示:
Google API Doc 官方说明:
TextInputLayout
TextInputLayout功能非常简单,就是用于用户在EditText中输入时hint的提示和错误的提示。
先来看看效果图吧:
从上图很明显的看出:
1、当EditText获得焦点时候,TextInputLayout会在左上角默认生成一个Label用来显示EditText中hint的内容,所以当用户输入时候hint内容会浮动到左上角,这极大便利了用户输入提交数据的体验。
2、当EditText中输入的内容不合法时,TextInputLayout便会在EditText的左下角用红色显示错误的提示信息。
下面来看看怎么用代码实现上面功能吧:
先看看布局文件:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin"> <Button android:id="@+id/snackBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="SnackBar" android:layout_margin="10dp"/> <android.support.design.widget.TextInputLayout android:id="@+id/til_name" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:id="@+id/til_password" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.design.widget.TextInputLayout></LinearLayout>
在Java代码中实现:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); til_name = (TextInputLayout) findViewById(R.id.til_name); til_password = (TextInputLayout) findViewById(R.id.til_password); //设置Hint信息 til_name.setHint("Name"); til_password.setHint("Password"); //设置输入监听 til_name.getEditText().addTextChangedListener(new MyTextWatcher(til_name, "用户名长度不能小于6位")); til_password.getEditText().addTextChangedListener(new MyTextWatcher(til_password, "密码长度不能小于6位")); } //自定义监听器 class MyTextWatcher implements TextWatcher { private TextInputLayout mTextInputLayout; private String errorInfo; public MyTextWatcher(TextInputLayout textInputLayout, String errorInfo) { this.mTextInputLayout = textInputLayout; this.errorInfo = errorInfo; } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (mTextInputLayout.getEditText().getText().toString().length() < 6) { mTextInputLayout.setErrorEnabled(true);//打开错误提示 mTextInputLayout.setError(errorInfo);//设置错误提示信息 } else { mTextInputLayout.setErrorEnabled(false);//关闭错误提示 } } }
其中,需要注意以下几点:
1、TextInputLayout布局中只能包含一个EditText子View,不能包含多个EditText。
2、TextInputLayout中有个方法getEditText();该方法返回的是它的子EditText对象,所以我们可通过mTextInputLayout.getEditText();来得到EditText对象,不需要findViewById找了。
3、设置错误提示信息时一定要先setErrorEnabled(true);再设置setError(…);因为TextView只在setErrorEnabled(true)方法中创建,必须创建好TextView才能往TextView上设置信息。而不需要设置时直接setErrorEnabled(false);即可,因为它自身会remove移除TextView。
4、TextInputLayout的颜色来自style中的colorAccent的颜色。
<item name="colorAccent">#FF4081</item>
Google API Doc 官方说明:
Floating Action Button
FloatingActionButton 是一个负责显示界面基本操作的圆形悬浮按钮。FAB继承自ImageView,你可以使用android:src或者ImageView的任意方法,比如setImageDrawable()来设置FloatingActionButton里面的图标。
<android.support.design.widget.FloatingActionButton android:id="@+id/fab1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:src="@drawable/good"/>
其他设置:
注意:使用以下属性时,需要在Layout中添加命名空间:xmlns:app=”http://schemas.android.com/apk/res-auto”
(1)悬浮操作按钮支持两种size(normal和mini),默认是normal,可以通过app:fabSize指定。
(2)FAB背景颜色默认取的是style中的colorAccent,可以通过app:backgroundTint来指定。
(3)FAB点击时颜色效果默认取的是theme中的colorControlHighlight,可以通过app:rippleColor来指定。
(4)和立体感相关有两个属性,elevation和pressedTranslationZ,前者用户设置正常显示的阴影大小;后者是点击时显示的阴影大小。
<android.support.design.widget.FloatingActionButton android:id="@+id/fab2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/good" app:fabSize="mini" app:backgroundTint="#ff0000ff" app:rippleColor="#ff00ff00" app:elevation="6dp" app:pressedTranslationZ="12dp"/>
TabLayout
通过选项卡的方式切换View并不是MD中才有的新概念,但是Google却是第一次在support库中提供了完整的支持,而且,Design library的TabLayout 既实现了固定的选项卡 (View的宽度平均分配),也实现了可滚动的选项卡(View宽度不固定同时可以横向滚动)。选项卡可以在程序中动态添加:
<android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabBackground="@color/colorPrimary" app:tabTextColor="#ffffffff" app:tabSelectedTextColor="#ffff0000" app:tabIndicatorColor="#ffffff00" app:tabIndicatorHeight="5dp" app:tabMode="fixed"/>
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);tabLayout.addTab(tabLayout.newTab().setText("tab1"));tabLayout.addTab(tabLayout.newTab().setText("tab2"));tabLayout.addTab(tabLayout.newTab().setText("tab3"));
但实际开发中我们很少这样用,通常滑动布局都会和ViewPager配合起来使用,所以,我们需要ViewPager来帮忙:
布局文件:
<android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabBackground="@color/colorPrimary" app:tabTextColor="#ffffffff" app:tabSelectedTextColor="#ffff0000" app:tabIndicatorColor="#ffffff00" app:tabIndicatorHeight="5dp" app:tabMode="fixed"/> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="wrap_content"/>
Java中设置ViewPager数据,并将ViewPager和TabLayout关联起来。
private void setupViewPager() { mInflater = LayoutInflater.from(this); view1 = mInflater.inflate(R.layout.tab_main, null); view2 = mInflater.inflate(R.layout.tab_main, null); view3 = mInflater.inflate(R.layout.tab_main, null); view4 = mInflater.inflate(R.layout.tab_main, null); view5 = mInflater.inflate(R.layout.tab_main, null); //添加页卡视图 mViewList.add(view1); mViewList.add(view2); mViewList.add(view3); mViewList.add(view4); mViewList.add(view5); //添加页卡标题 mTitleList.add("No:1"); mTitleList.add("No:2"); mTitleList.add("No:3"); mTitleList.add("No:4"); mTitleList.add("No:5"); mTabLayout.setTabMode(TabLayout.MODE_FIXED);//设置tab模式,当前为系统默认模式 mTabLayout.addTab(mTabLayout.newTab().setText(mTitleList.get(0))); mTabLayout.addTab(mTabLayout.newTab().setText(mTitleList.get(1))); mTabLayout.addTab(mTabLayout.newTab().setText(mTitleList.get(2))); mTabLayout.addTab(mTabLayout.newTab().setText(mTitleList.get(3))); mTabLayout.addTab(mTabLayout.newTab().setText(mTitleList.get(4))); MyPagerAdapter mAdapter = new MyPagerAdapter(mViewList, mTitleList); mViewPager.setAdapter(mAdapter);//给ViewPager设置适配器 mTabLayout.setupWithViewPager(mViewPager);//将TabLayout和ViewPager关联起来。 mTabLayout.setTabsFromPagerAdapter(mAdapter);//给Tabs设置适配器 }
ViewPager的Adapter适配器:
class MyPagerAdapter extends PagerAdapter { private List<View> mViewList; private List<String> mTitleList; public MyPagerAdapter(List<View> mViewList, List<String> mTitleList) { this.mViewList = mViewList; this.mTitleList = mTitleList; } @Override public int getCount() { return mViewList.size();//页卡数 } @Override public boolean isViewFromObject(View view, Object object) { return view == object;//官方推荐写法 } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(mViewList.get(position));//添加页卡 return mViewList.get(position); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(mViewList.get(position));//删除页卡 } @Override public CharSequence getPageTitle(int position) { return mTitleList.get(position);//页卡标题 }}
NavigationView
NavigationView在MD设计中非常重要,之前Google也提出了使用DrawerLayout来实现导航抽屉。这次,在support library中,Google提供了NavigationView来实现导航菜单界面,所以,新的导航界面可以这样写了:
<android.support.v4.widget.DrawerLayout android:id="@+id/dl_main_drawer" 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:fitsSystemWindows="true"> <!-- 你的内容布局--> <include layout="@layout/content"/> <android.support.design.widget.NavigationView android:id="@+id/nv_main_navigation" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/navigation_header" app:menu="@menu/drawer_view"/></android.support.v4.widget.DrawerLayout>
可以看到我们的最外层是DrawerLayout,里面一个content,一个作为drawer。我们的drawer为NavigationView。
其中NavigationView 中的 android:layout_gravity=”start” 属性来控制抽屉菜单从哪边滑出,一般 “start ”从左边滑出,“end”从右边滑出。
其中最重要的就是下面两个属性:
app:headerLayout
app:menu
通过这两个属性,我们可以非常方便的指定导航界面的头布局和菜单布局。
来看看headerLayout的布局文件(layout目录)和menu配置文件(menu目录):
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="200dp" android:background="#ff0000ff" android:gravity="center" android:orientation="vertical" android:padding="16dp" android:theme="@style/ThemeOverlay.AppCompat.Dark"> <ImageView android:layout_width="100dp" android:layout_height="100dp" android:layout_marginTop="16dp" android:background="@drawable/head"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" android:gravity="center" android:text="Watson" android:textSize="20sp"/></LinearLayout>
<?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/nav_home" android:icon="@drawable/setting" android:title="Home"/> <item android:id="@+id/nav_messages" android:icon="@drawable/setting" android:title="Messages"/> <item android:id="@+id/nav_friends" android:icon="@drawable/setting" android:title="Friends"/> <item android:id="@+id/nav_discussion" android:icon="@drawable/setting" android:title="Discussion"/> </group> <item android:title="Sub items"> <menu> <item android:icon="@drawable/star" android:title="Sub item 1"/> <item android:icon="@drawable/star" android:title="Sub item 2"/> </menu> </item></menu>
默认的颜色很多是从当前的主题中提取的,比如icon的stateColor,当然你也可以通过以下方法或属性修改部分样式:
- setItemBackgroundResource(int):给menu设置背景资源,对应的属性app:itemBackground
- setItemIconTintList(ColorStateList):给menu的icon设置颜色,对应的属性app:itemIconTint
- setItemTextColor(ColorStateList):给menu的item设置字体颜色,对应的属性app:itemTextColor
你可以通过设置一个OnNavigationItemSelectedListener,使用其setNavigationItemSelectedListener()来获得元素被选中的回调事件。它为你提供被点击的 菜单元素 ,让你可以处理选择事件,改变复选框状态,加载新内容,关闭导航菜单,以及其他任何你想做的操作。例如这样:
private void setupDrawerContent(NavigationView navigationView) { navigationView.setNavigationItemSelectedListener( new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { menuItem.setChecked(true); mDrawerLayout.closeDrawers(); return true; } }); }
同时,为了不遮住导航抽屉,我们选择隐藏ActionBar:
隐藏可以通过修改我们继承的主题为:Theme.AppCompat.Light.NoActionBar,当然也可以通过设置以下属性完成:
<item name="windowActionBar">false</item><item name="windowNoTitle">true</item>
我们这里选择前者:
<style name="AppBaseTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- customize the color palette --> <item name="colorPrimary">#673AB7</item> <item name="colorPrimaryDark">#512DA8</item> <item name="colorAccent">#FF4081</item></style>
<application ... android:theme="@style/AppTheme"> ...</application>
来看看运行效果
效果不错,不过存在一个问题,此时如果你点击Sub items里面的Sub item,发现它一直是选中状态,点击多个Sub item后会出现多个同时选中的情况。那怎么办呢?只能我们来手动切换了:
navigationView.setNavigationItemSelectedListener( new NavigationView.OnNavigationItemSelectedListener() { private MenuItem mPreMenuItem; @Override public boolean onNavigationItemSelected(MenuItem menuItem) { if (mPreMenuItem != null) mPreMenuItem.setChecked(false); menuItem.setChecked(true); //关闭抽屉侧滑菜单 mDrawerLayout.closeDrawers(); mPreMenuItem = menuItem; return true; } });
这里我们的导航菜单是通过手势滑动打开的,其实我们也可以通过函数实现:
/**打开抽屉侧滑菜单*/mDrawerLayout.openDrawer(GravityCompat.START);
Toolbar
众所周知,在使用ActionBar的时候,一堆的问题:位置固定在顶部不能改变,文字不能定制,图标的间距不能控制等等,由此暴露出了ActionBar的设计不够灵活。为此官方提供了ToolBar,并且提供了supprot library用于向下兼容。Toolbar之所以灵活,是因为它其实就是一个ViewGroup,我们在使用的时候和普通的组件一样,在布局文件中声明。下面来看看Toolbar的使用。
首先隐藏原本的ActionBar,实现方式见上面NavigationView一节。
接下来就是将Toolbar放入到布局文件:
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:background="?attr/colorPrimary" android:layout_height="?android:attr/actionBarSize"/>
最后可以将Toobar作为“ActionBar”来用,对Toolbar设置Nav Icon、Logo、Title 、Sub Title、Menu Items。
关于字体的样式,可以在布局文件设置属性app:titleTextAppearance、app:subtitleTextAppearance或者代码setTitleTextAppearance、setSubTitleTextAppearance设置。
至于Menu Item,依然支持在menu/menu_main.xml中去声明,然后复写onCreateOptionsMenu和onOptionsItemSelected即可。
也可以通过toolbar.setOnMenuItemClickListener实现点击MenuItem的回调。
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { if(item.getItemId() == ...) { /**do something*/ return true; } return false; } });
Java代码实现:
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);toolbar.setTitle("这里是Title");toolbar.setSubtitle("这里是子标题");toolbar.setLogo(R.drawable.head); toolbar.setNavigationIcon(R.drawable.ic_menu);setSupportActionBar(toolbar); @Override public boolean onOptionsItemSelected(MenuItem item) { /**监听Nav Icon的点击事件*/ if(item.getItemId() == android.R.id.home) { Toast.makeText(MainActivity.this,"NavigationIcon clicked",Toast.LENGTH_SHORT).show(); return true; } return super.onOptionsItemSelected(item); }
AppBarLayout
AppBarLayout 是继承LinerLayout实现的一个ViewGroup容器组件,它是为了Material Design设计的App Bar,支持手势滑动操作。默认的AppBarLayout是垂直方向的,它的作用是把AppBarLayout包裹的内容都作为AppBar。
下面演示将Toolbar 和TabLayout的组合部分共同构成 AppBar的效果。
<android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?android:attr/actionBarSize" android:background="?attr/colorPrimary" /> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabBackground="?attr/colorPrimary" app:tabIndicatorColor="#ffffff00" app:tabIndicatorHeight="5dp" app:tabMode="fixed" app:tabSelectedTextColor="#ffff0000" app:tabTextColor="#ffffffff" /> </android.support.design.widget.AppBarLayout>
注: AppBarLayout必须作为Toolbar的父布局容器
AppBarLayout是支持手势滑动效果的,不过要和CoordinatorLayout配合使用,接下来学习一下CoordinatorLayout组件怎么使用。
CoordinatorLayout
CoordinatorLayout是这次新添加的一个增强型的FrameLayout。在CoordinatorLayout中,我们可以在FrameLayout的基础上完成很多新的操作。它的作用主要是协调子view之间触摸事件的布局。
首先看一个例子,当你将FloatingActionButton作为一个子View添加进CoordinatorLayout并且将CoordinatorLayout传递给 Snackbar.make(),在3.0及其以上的设备上,Snackbar不会显示在悬浮按钮的上面,而是FloatingActionButton利用CoordinatorLayout提供的回调方法,在Snackbar以动画效果进入的时候自动向上移动让出位置,并且在Snackbar动画地消失的时候回到原来的位置,不需要额外的代码。
<android.support.design.widget.CoordinatorLayout android:id="@+id/coordinatorLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.FloatingActionButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/good" android:layout_gravity="center_horizontal" app:backgroundTint="#ff0000ff" app:elevation="6dp" app:fabSize="mini" app:pressedTranslationZ="12dp" app:rippleColor="#ff00ff00" /> </android.support.design.widget.CoordinatorLayout>
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);...@Override public void onClick(View v) { switch (v.getId()) { case R.id.snackBar: Snackbar.make(coordinatorLayout, "Snackbar comes out", Snackbar.LENGTH_LONG) .setAction("Action", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText( MainActivity.this,"Toast comes out",Toast.LENGTH_SHORT).show(); } }).show(); break; default: break; } }
再来看看官方给出的例子:
<android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="200dp"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?android:attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways"/> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabBackground="?attr/colorPrimary" app:tabIndicatorColor="#ffffff00" app:tabIndicatorHeight="5dp" app:tabMode="fixed" app:tabSelectedTextColor="#ffff0000" app:tabTextColor="#ffffffff"/> </android.support.design.widget.AppBarLayout> </android.support.design.widget.CoordinatorLayout>
从上面布局看到,CoordinatorLayout协调布局中包裹了两个布局,一个是RecyclerView,一个是AppBarLayout,并且:
1、给这个可滚动组件设置了layout_behavior
2、给另一个控件设置了layout_scrollFlags
为滚动的布局设置layout_behavior属性后,这个布局会自动移动到AppBarLayout以下(类似MarginTop)。而且,当设置了layout_behavior的控件滑动时,就会触发设置了layout_scrollFlags的控件发生状态的改变。
layout_behavior:coordinatorlayout可以协调子view之间的触动事件,每一个子view需要有各自的滑动处理方式。该属性就是用来指定处理自己滑动事件的Behavior对象。因此,该属性的值为自定义Behavior子类的全名(即包名+类名)。本例如下:
app:layout_behavior="@string/appbar_scrolling_view_behavior"...<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
layout_scrollFlags有如下几种选项:
- scroll: 所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。
- enterAlways: 这个flag让任意向下的滚动都会导致该view变为可见,启用快速“返回模式”。
- enterAlwaysCollapsed:当你的视图已经设置minHeight属性又使用此标志时,你的视图只能以最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。
- exitUntilCollapsed: 向上滚动时收缩View,但可以固定Toolbar一直在上面。
需要注意的是,后面两种模式基本只有在CollapsingToolbarLayout才有用,而前面两种模式基本是需要一起使用的,也就是说,这些flag的使用场景,基本已经固定了。
例如我们前面例子中的,也就是这种模式:
app:layout_scrollFlags="scroll|enterAlways"
我们上面的布局中 给Toolbar设置了app:layout_scrollFlags属性,因此,Toolbar是可以滚动出屏幕,且向下滚动又可以出现。
为了使得Toolbar可以滑动,我们必须还得有个条件,就是CoordinatorLayout布局下包裹一个具有滑动效果的组件,比如 RecyclerView,NestedScrollView(经过测试,ListView,ScrollView不支持)。并且给这些组件设置layout_behavior属性来告诉CoordinatorLayout,该组件是带有滑动行为的组件,然后CoordinatorLayout在接受到滑动时会通知AppBarLayout 中可滑动的Toolbar可以滑出屏幕了。
注:所有使用scrollFlags的view都必须定义在没有使用scrollFlags的view的前面,这样才能确保所有的view从顶部退出,留下固定的元素。
CollapsingToolbarLayout
CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承自FrameLayout,给它设置layout_scrollFlags,它可以控制包含在CollapsingToolbarLayout中的控件(如:ImageView、Toolbar)在响应layout_behavior事件时作出相应的scrollFlags滚动事件(移除屏幕或固定在屏幕顶端)。
使用CollapsingToolbarLayout:
<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="256dp" android:fitsSystemWindows="true"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_toolbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="#30469b" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" android:src="@drawable/ic_banner" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.7" /> <android.support.v7.widget.Toolbar android:id="@+id/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> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="none" /> </LinearLayout></android.support.design.widget.CoordinatorLayout>
我们在CollapsingToolbarLayout中设置了一个ImageView和一个Toolbar。并把这个CollapsingToolbarLayout放到AppBarLayout中作为一个整体。
(1)在CollapsingToolbarLayout中,设置了app:layout_scrollFlags=”scroll|exitUntilCollapsed”。关于layout_scrollFlags的值意义见上面。
其中还设置了一些属性,简要说明一下:
contentScrim – 设置当完全CollapsingToolbarLayout折叠(收缩)后的背景颜色。
expandedTitleMarginStart – 设置扩张时候(还没有收缩时)title向左填充的距离。
(2)在ImageView控件中,我们设置了:
layout_collapseMode (折叠模式) – 有两个值:
- pin - 设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。
- parallax - 设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,通常和layout_collapseParallaxMultiplier(设置视差因子)搭配使用。
layout_collapseParallaxMultiplier(视差因子) - 设置视差滚动因子,值为:0~1。
(3)在Toolbar控件中,我们设置了layout_collapseMode(折叠模式):为pin。
综上分析:当设置了layout_behavior的控件响应起了CollapsingToolbarLayout中的layout_scrollFlags事件时,ImageView会有视差效果的向上滚动移除屏幕,当开始折叠时CollapsingToolbarLayout的背景色(也就是Toolbar的背景色)就会变为我们设置好的背景色,Toolbar也一直会固定在最顶端。
效果如图:
Java代码:
mToolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(mToolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); /**使用CollapsingToolbarLayout必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上则不会显示*/ mCollapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar_layout); mCollapsingToolbarLayout.setTitle("CollapsingToolbarLayout"); //通过CollapsingToolbarLayout修改字体颜色 mCollapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);//设置还没收缩时状态下字体颜色 mCollapsingToolbarLayout.setCollapsedTitleTextColor(Color.GREEN);//设置收缩后Toolbar上字体的颜色
注:使用CollapsingToolbarLayout时必须把title设置到CollapsingToolbarLayout上,设置到Toolbar上不会显示。
Demo下载地址
- Android Design Support Library
- Android Design Support Library
- Android Design Support Library
- Android Design Support Library
- Android Design Support Library
- android Design Support Library
- Android Design Support Library
- Android Design Support Library
- Android Design Support Library
- Android Design Support Library学习
- Android Material Design support library
- Android Design Support Library概览
- Android Design Support Library 介绍
- Android Design Support Library详解
- Android Support Design Library - CoordinatorLayout
- Android Design Support Library 使用
- Android Design Support Library - FloatingActionButton
- Android Design Support Library使用
- RTP协议详解
- Fragment 文章 待整理
- jquery实现动态创建页面元素(ul,li列表实例)
- SQL 触发器的作用,好处和坏处
- 判断是否为C++合法标识符
- Android Design Support Library
- oAuth
- PHP调试时echo print() print_r() var_dump()的区别
- 找工作之Effective C++
- 状态压缩
- WEEX|初始化工程
- GObject 学习笔记汇总---7
- clang static analyzer源码分析(番外篇):RegionStore以及evalCall()中的conservativeEvalCall
- UVA 10723