Android Design Support Library 是Google在2015年的IO大会上,带来的全新适应Material Design设计规范的支持库。在这个支持库中,给我们提供了更加规范的MD设计风格控件。重要的是,Android Design Support Library中,支持所有的Android 2.1以上版本系统。在这个支持库中,主要包含下面几大控件:
Snackbar,FloatingActionButton,TextInputLayout,TabLayout,AppBarLayout,CollapsingToolbarLayout,NavigationView,CoordinatorLayout
在使用Android Design Support Library之前,我们只需要在AS中添加引用即可:
compile 'com.android.support:design:23.3.0'
下面我们将分别介绍各个控件的使用。
Snackbar提供了关于操作的轻量级的反馈。它可以从屏幕底部展示一个简短的消息,与Toast相似,但是它更灵活和功能更加强大。
当它显示一段时间后或者用户与屏幕交互时,它会自动消失;
可以包含一个动作action;
Snackbar出现在屏幕所有其他元素之上,同一时间内只有一个Snackbar显示。
使用Snackbar
Snackbar bar = Snackbar.make(view,"Hello Snackbar",Snackbar.LENGTH_SHORT);
bar.show();
方法:
make (View view, CharSequence text, int duration) -生成Snackbar消息
show () -开始显示Snackbar消息
参数:
view,Snackbar会通过该view寻找一个父View来持有Snackbar的view。
text,显示的消息
duration,与Toast一样,控制Snackbar的显示时间。
我们可以为Snackbar添加一个点击动作Action,如下:
Snackbar bar = Snackbar.make(view,"Hello Snackbar",Snackbar.LENGTH_SHORT);
bar.setAction("Action", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,"点击了!",Toast.LENGTH_SHORT).show();
}
});
bar.show();
上面增加一个可点击的动作,点击“ACTION”时,弹出Toast框。
我们还可以修改Snackbar的样式
Snackbar bar = Snackbar.make(view,"Hello Snackbar",Snackbar.LENGTH_SHORT);
bar.setAction("动作", new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,"点击了!",Toast.LENGTH_SHORT).show();
}
});
bar.setActionTextColor(Color.WHITE); //设置Aciton的字体颜色值
Snackbar.SnackbarLayout layout = (Snackbar.SnackbarLayout) bar.getView();
layout.setBackgroundColor(Color.RED); //设置Snackbar的背景色
TextView textView = (TextView) layout.findViewById(R.id.snackbar_text);
textView.setTextColor(Color.WHITE); //设置Snackbar文字的颜色
bar.show();
FloatingActionButton是悬浮按钮,用来强调当前屏幕中最重要的动作,吸引用户的注意。FloatingActionButton现在是继承自控件ImageButton,所以它也会拥有该控件的所有属性。
使用FloatingActionButton
.support.design.widget.FloatingActionButton
android:id="@+id/fabutton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
我们可以看到FAB有一个背景颜色,默认的背景颜色取的是theme中的colorAccent的值,可以在style中定义的colorAccent设置。
我们同样也可以自行单独设置其它的属性:
app:backgroundTint:设置FAB的背景颜色。
app:rippleColor:设置FAB点击时的背景颜色。
app:elevation:设置默认状态下FAB的阴影大小。
app:pressedTranslationZ:点击时候FAB的阴影大小。
app:fabSize:设置FAB的大小,该属性有两个值,分别为normal和mini,对应的FAB大小分别为56dp和40dp。
app:layout_anchor:设置FAB的锚点,即以哪个控件为参照点设置位置。 <—该属性需要在CoordinatorLayout布局中使用才生效—->
app:layout_anchorGravity:设置FAB相对锚点的位置,值有 bottom、center、right、left、top等。 <—该属性需要在CoordinatorLayout布局中使用才生效—->
继续给添加FAB的点击事件,与Snackbar配合使用时,会出现Snackbar遮住FAB的情况,如:
出现这样的情况,会让用户体验不友好,正确的应该让浮动操作按钮上下滑动,为Snackbar留出空间。
为了解决该问题,我们这里就用到了另一个控件CoordinatorLayout,关于这个控件之后在讲解。
TextInputLayout继承自LinearLayout,用来把EditText包裹在该布局中,可以让hint文字变成一个在EditText上方的浮动标签,同时还包括一个漂亮的material动画。TextInputLayout只接受一个子元素。子元素需要是一个EditText元素。
使用TextInputLayout
.support.design.widget.TextInputLayout
android:id="@+id/textinput_username"
android:layout_width="match_parent"
android:layout_height="wrap_content">
"match_parent"
android:layout_height="wrap_content"
android:hint="username" />
.support.design.widget.TextInputLayout>
获取控件EditText对象
TextInputLayout和LinearLayout和ScrollView不同,你可以使用一个特殊的方法获得子元素EditText,getEditText,不需要使用findViewById。
如:
textinput_username = (TextInputLayout) findViewById(R.id.textinput_username);
EditText username = textinput_username.getEditText();
显示错误信息
TextInputLayout的错误处理简单快速。需要的方法是setErrorEnabled和setError。
使用setError时,错误信息会出现在EditText的下面。使用setErrorEnabled可以隐藏错误信息。
如:
public void handleClick(View view) {
String username = textinput_username.getEditText().getText().toString();
if (TextUtils.isEmpty(username)) {
textinput_username.setError("请输入用户名!");
} else {
textinput_username.setError(null); //必须添加,否则出现错误信息第二次不显示的问题
textinput_username.setErrorEnabled(false);
}
}
TabLayout提供了一个水平布局来显示tabs。可以实现TabPageIndicator或PagerTabStrip相同的效果了。与ViewPager配合使用可发挥它的优势。
布局文件:
"1.0" encoding="utf-8"?>
"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:orientation="vertical">
.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="@color/colorAccent"
app:tabSelectedTextColor="@color/colorAccent"
app:tabTextColor="@color/colorPrimaryDark">
.support.design.widget.TabLayout>
.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
.support.v4.view.ViewPager>
常用的属性:
app:tabIndicatorColor:Tab指示器下标的颜色
app:tabSelectedTextColor:Tab被选中时字体的颜色
app:tabTextColor:Tab未被选中时字体的颜色
Activity中调用
tablayout = (TabLayout) findViewById(R.id.tablayout);
tablayout.setTabMode(TabLayout.MODE_FIXED);
tablayout.addTab(tablayout.newTab().setText("Tab 1"));
tablayout.addTab(tablayout.newTab().setText("Tab 2"));
tablayout.addTab(tablayout.newTab().setText("Tab 3"));
tablayout.addTab(tablayout.newTab().setText("Tab 4"));
tablayout.addTab(tablayout.newTab().setText("Tab 5"));
tablayout.addTab(tablayout.newTab().setText("Tab 6"));
tablayout.setTabMode()中存在两种选择:
TabLayout.MODE_FIXED:不支持水平滑动
TabLayout.MODE_SCROLLABLE:支持水平滑动效果
配合ViewPager的使用完整代码:
viewpager = (ViewPager) findViewById(R.id.viewpager);
tablayout = (TabLayout) findViewById(R.id.tablayout);
tablayout.setTabMode(TabLayout.MODE_SCROLLABLE);
viewpager.setAdapter(pagerAdapter);
tablayout.setupWithViewPager(viewpager);
tablayout.getTabAt(0).setText("Tab 1");
tablayout.getTabAt(1).setText("Tab 2");
tablayout.getTabAt(2).setText("Tab 3");
tablayout.getTabAt(3).setText("Tab 4");
tablayout.getTabAt(4).setText("Tab 5");
tablayout.getTabAt(5).setText("Tab 6");
tablayout.getTabAt(6).setText("Tab 7");
tablayout.getTabAt(7).setText("Tab 8");
tablayout.getTabAt(8).setText("Tab 9");
tablayout.getTabAt(9).setText("Tab 10");
注意:
设置tab栏信息时,要在
viewpager.setAdapter(pagerAdapter);
tablayout.setupWithViewPager(viewpager);之后,否则会出现tab上的文字不显示的问题。具体原因可以通过查看setupWithViewPager方法内部,里面执行了removeAllTabs()的操作。所以需要重新设置tabs中的标题信息。
效果图:
AppBarLayout是一个垂直的线性布局,实现了许多MD的特性,包括滚动手势。
它的子View通过 setScrollFlags(int) 方法或者设置app:layout_scrollFlags属性来提供滚动的行为。但是必须是作为CoordinatorLayout的直接子view,这些行为才会生效。
1.实现上滑隐藏,下滑显示的效果。(CoordinatorLayout + AppBarLayout + Toolbar + TabLayout)
布局文件设置:
<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/appbar_layout"
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="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:logo="@mipmap/ic_launcher"
app:navigationIcon="@mipmap/ic_drawer_home"
app:subtitle="subtitle"
app:title="title" />
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:tabSelectedTextColor="@color/colorAccent"
app:tabTextColor="@android:color/white" />
android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android.support.v4.widget.NestedScrollView>
android.support.design.widget.CoordinatorLayout>
总结如下:
根布局控件必须是CoordinatorLayout;
toolbar要放在布局AppBarLayout中;
toolbar需要设置属性app:layout_scrollFlags=”scroll|enterAlways”;
在RecyclerView或者任意支持嵌套滚动的view比如NestedScrollView上添加属性app:layout_behavior=”@string/appbar_scrolling_view_behavior”,这样才能和AppBarLayout联动
CollapsingToolbarLayout被用来包裹Toolbar,实现了一个可折叠的app bar。它用来作为AppBarLayout的子类。CollapsingToolbarLayout还可以包含一个ImageView,用来作为滑动时的背景。
在CollapsingToolbarLayout中有几个常见的属性设置:
app:contentScrim=”@color/colorPrimary”:设置当CollapsingToolbarLayout完全折叠(收缩)后的背景颜色;
app:expandedTitleMarginStart=”48dp”:设置CollapsingToolbarLayout处于扩张时(未收缩)时,title距离左边的距离;
app:layout_scrollFlags=”scroll|exitUntilCollapsed”:设置滚动标志,这里面有几个值:
scroll:想滚动就必须设置这个。
enterAlways:实现quick return效果, 当向下移动时,立即显示View(比如Toolbar)。
exitUntilCollapsed:向上滚动时收缩View时,Toolbar一直固定在上面。
enterAlwaysCollapsed:当你的View已经设置minHeight属性又使用此标志时,你的View只能以最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。
在CollapsingToolbarLayout中子ImageView的常见设置:
app:layout_collapseMode=”parallax”:设置子布局设置折叠模式
parallax:视差模式,在折叠的时候会有个视差折叠的效果。
pin:固定模式,在折叠的时候最后固定在顶端
app:layout_collapseParallaxMultiplier=”0.7”:设置视差的系数,介于0.0-1.0之间。
在CollapsingToolbarLayout中Toolbar的设置:
app:layout_collapseMode=”pin”:当CollapsingToolbarLayout完全收缩后, Toolbar还可以保留在屏幕上。
注:
1.使用CollapsingToolbarLayout时,必须把title设置到CollapsingToolbarLayout上,如果设置在Toolbar上不显示。
2.设置title的字体颜色:
扩张时候的title颜色:mCollapsingToolbarLayout.setExpandedTitleColor();
收缩后在Toolbar上显示时的title的颜色:mCollapsingToolbarLayout.setCollapsedTitleTextColor();
完整布局文件:
"1.0" encoding="utf-8"?>
.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">
.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="256dp">
.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="@color/colorPrimary"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:title="@string/app_name">
"match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:src="@drawable/pic4"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7" />
.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
.support.design.widget.CollapsingToolbarLayout>
.support.design.widget.AppBarLayout>
.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
.support.v4.widget.NestedScrollView>
.support.design.widget.CoordinatorLayout>
代码文件:
toolbar = (Toolbar) findViewById(R.id.toolbar);
collapsing_layout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_layout);
collapsing_layout.setExpandedTitleColor(Color.RED);//设置还没收缩时状态下字体颜色
collapsing_layout.setCollapsedTitleTextColor(Color.GREEN);//设置收缩后Toolbar上字体的颜色
总结:
1.根布局控件必须是CoordinatorLayout
2.AppBarLayout包含CollapsingToolbarLayout布局,CollapsingToolbarLayout需要指定属性
app:layout_scrollFlags=”scroll|exitUntilCollapsed” 向上滚动收缩view
app:contentScrim=”@color/colorPrimary” 折叠后的背景颜色
3.CollapsingToolbarLayout中包含视差图片的控件ImageView和Toolbar 两个子控件。
4.设置视差控件ImageView的两个属性:
app:layout_collapseMode=”parallax”
app:layout_collapseParallaxMultiplier=”0.7”
5.为了和视差控件ImageView交互,需要设置ToolBar的属性
app:layout_collapseMode=”pin”
6.给带scroll属性的控件,比如NestedScrollView或者ScrollView,需要指定属性:
app:layout_behavior=”@string/appbar_scrolling_view_behavior”
7.如果存在FloatingActionButton,指定属性
app:layout_anchor=”@id/appbar_layout” //锚点定在AppBarLayout上,则可以随视差滚动联动
CoordinatorLayout 是一个非常强大的FrameLayout布局。
主要实现两个基本的功能:
作为布局的顶层节点。
协调子View的调度。
1.CoordinatorLayout 与 FloatingActionButton
可以让FAB上下滑动,为Snackbar流出空间。
布局文件:
<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">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/listview"
app:layout_anchorGravity="bottom|right" />
android.support.design.widget.CoordinatorLayout>
Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.content_main);
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
Snackbar.make(fab,"点击了",Snackbar.LENGTH_LONG).show();
}
});
}
关于CoordinatorLayout 与 AppBarLayout /CollapsingToolbarLayout 可以查看上面的介绍。
8.NavigationView
NavigationView表示一个标准的应用程序导航菜单,菜单可以有标准的menu资源文件填充。
NavigationView常见的是放在DrawerLayout中使用。
使用NavigationView
1.activity_main.xml的布局文件
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="mo.yumf.com.mddemo.MainActivity">
<include layout="@layout/content_main">include>
<android.support.design.widget.NavigationView
android:id="@+id/navigationview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/header_layout"
app:menu="@menu/menu_drawer" />
android.support.v4.widget.DrawerLayout>
里面include了一个布局文件content_main.xml
<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">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/listview"
app:layout_anchorGravity="bottom|right" />
android.support.design.widget.CoordinatorLayout>
接着看到NavigationView中,有两个属性app:headerLayout=”@layout/header_layout”,app:menu=”@menu/menu_drawer” ,分别代表drawer布局中的header和menuitem的区域。
header_layout.xml 文件如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp"
android:gravity="center"
android:background="@color/colorPrimary"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" />
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
LinearLayout>
menu_drawer.xml布局文件:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group>
<item
android:id="@+id/nav_home"
android:checkable="true"
android:icon="@mipmap/ic_notifications"
android:title="Home" />
<item
android:id="@+id/nav_messages"
android:checkable="true"
android:icon="@mipmap/ic_notifications"
android:title="Messages" />
<item
android:id="@+id/nav_friends"
android:checkable="true"
android:icon="@mipmap/ic_notifications"
android:title="Friends" />
<item
android:id="@+id/nav_discussion"
android:checkable="true"
android:icon="@mipmap/ic_notifications"
android:title="Discussion" />
group>
<item android:title="Sub items">
<menu>
<item
android:checkable="true"
android:icon="@mipmap/ic_notifications"
android:title="Sub item 1" />
<item
android:checkable="true"
android:icon="@mipmap/ic_notifications"
android:title="Sub item 2" />
menu>
item>
menu>
2.Activity中代码:
public class MainActivity extends AppCompatActivity {
private FloatingActionButton fab;
private DrawerLayout drawerLayout;
private NavigationView navigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fab = (FloatingActionButton) findViewById(R.id.fab);
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
navigationView = (NavigationView) findViewById(R.id.navigationview);
setupDrawerContent(navigationView);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
drawerLayout.openDrawer(Gravity.LEFT);
}
});
}
private void setupDrawerContent(NavigationView navigationView) {
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
private MenuItem mPreMenuItem;
@Override
public boolean onNavigationItemSelected(MenuItem item) {
//每次只能选择一个item
if (mPreMenuItem != null){
mPreMenuItem.setChecked(false);
}
item.setChecked(true);
drawerLayout.closeDrawers();
mPreMenuItem = item;
return true;
}
});
//设置默认选中的item
navigationView.getMenu().getItem(0).setChecked(true);
}
}
自定义该背景色
上面的menuItem 使用的是默认属性,直接采用主题的颜色。
我们可以进行自定义该背景色,通过设置属性:
app:itemTextColor="@color/menu_item_color"
app:itemIconTint="@color/menu_item_color"
首先在res/color文件下创建一个selector文件menu_item_color.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/colorAccent" android:state_checked="true" />
<item android:color="@color/colorAccent" android:state_pressed="true" />
<item android:color="@color/colorAccent" android:state_focused="true" />
<item android:color="@color/colorPrimary" />
selector>