Design Support Library是在Google I/O 2015上发布的一个全新兼容函数库,它使得开发者可以在Android2.1(API = 7)及以上的设备中实现Material Design效果,这个函数库提供了一系列的控件,主要包括:Snackbar,Navigation View、FloatActionButton、CoordinatorLayout、CollapsingToolbarLayout等。
在使用Design Support Library 之前,首先需要添加如下依赖:
dependencies {
compile 'com.android.support:design:25.2.0'
}
Snackbar
Snackbar提供了一个介于Toast和AlertDialog之间轻量级控件,它可以很方便的提供消息的提示和动作反馈。
Snackbar的使用与Toast的使用基本相同:
Snackbar.make(view, "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显示的基准元素,而设置的Action也可以设置多个。
显示的效果就类似如下:
Snackbar在出现一定时间后,就会消失,这与Toast一模一样。
TextInputLayout
TextInputLayout的主要作用是作为EditText的容器,从而为EditText默认生成一个浮动的Label,当用户点击EditText之后,EditText中设置的hint字符串会自动移动到EditText的左上角。TextInputLayout的使用很简单,语句如下,将它作为EditText的父容器即可。同时,如果给EditText增加监听,还可以给它增加更多的floating label。
下面我们来看这与一个TextInputLayout:
<android.support.design.widget.TextInputLayout
android:id="@+id/til_pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
一定要注意,他是把EditText包含起来的,不能单独使用。
在代码中,我们给它设置监听:
//TextInputLayout
textInputLayout = (TextInputLayout) findViewById(R.id.til_pwd);
EditText editText = textInputLayout.getEditText();
textInputLayout.setHint("Password");
editText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (s.length() > 4) {
textInputLayout.setError("Password error");
textInputLayout.setErrorEnabled(true);
} else {
textInputLayout.setErrorEnabled(false);
}
}
@Override
public void afterTextChanged(Editable s) {
}
});
这样:显示效果如下:
当输入时:
这里需要注意的是,TextInputLayout的颜色来自style中的colorAccent的颜色:
<item name="colorAccent">#1743b7</item>
TabLayout
Tablayout控件用于在应用中轻松添加Tab分组功能,总共有两种类型可供选择。
- 固定Tabs:对应xml配置中的app:tabMode=”fixed”。
- 可滑动的Tabs:对应xml配置中的app:tabMode=”scrollable”。
选项卡可以在程序中动态添加:
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来帮忙:
mViewPager = (ViewPager) findViewById(R.id.viewpager);
// 设置ViewPager的数据等
setupViewPager();
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
// 非常重要,将ViewPager和TabLayout结合了起来
tabLayout.setupWithViewPager(mViewPager);
通过一句话setupWithViewPager,我们就把ViewPager和TabLayout结合了起来。
NavigationView
NavigationView在MD设计中非常重要,之前Google也提出了使用DrawerLayout来实现导航抽屉。这次,在support library中,Google提供了NavigationView来实现导航菜单界面,所以,新的导航界面可以这样写了:
<?xml version="1.0" encoding="utf-8"?>
<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/navigation_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>
其中最重要的就是这两个属性:
app:headerLayout
app:menu
通过这两个属性,我们可以非常方便的指定导航界面的头布局和菜单布局:
其中最上面的布局就是app:headerLayout所指定的头布局:
<?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="192dp"
android:background="?attr/colorPrimaryDark"
android:gravity="center|left"
android:orientation="vertical"
android:paddingTop="30dp"
android:paddingLeft="16dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark">
<ImageView
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:scaleType="centerCrop"
android:background="@drawable/ic_user"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="JiaMengfei"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="不负韶华,砥砺前行!"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>
</LinearLayout>
而下面的菜单布局,我们可以直接通过menu内容自动生成,而不需要我们来指定布局:
<?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/customerservice"
android:title="Home"/>
<item
android:id="@+id/nav_messages"
android:icon="@drawable/my_library"
android:title="Messages"/>
<item
android:id="@+id/nav_friends"
android:icon="@drawable/my_delegation"
android:title="Friends"/>
<item
android:id="@+id/nav_discussion"
android:icon="@drawable/buy"
android:title="Discussion"/>
</group>
<item android:title="Version">
<menu>
<item
android:icon="@drawable/financecenter"
android:title="Android"/>
<item
android:icon="@drawable/financecenter"
android:title="iOS"/>
</menu>
</item>
</menu>
你可以通过设置一个OnNavigationItemSelectedListener,使用其setNavigationItemSelectedListener()来获得元素被选中的回调事件。它为你提供被点击的 菜单元素 ,让你可以处理选择事件,改变复选框状态,加载新内容,关闭导航菜单,以及其他任何你想做的操作。例如这样:
// 图片都变为灰色的破解方法
NavigationView navigationView = (NavigationView) findViewById(R.id.nv_main_navigation);
navigationView.setItemIconTintList(null);
if(navigationView != null) {
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
Snackbar.make(tablayoutContent,
menuItem.getTitle()+" pressed",Snackbar.LENGTH_LONG).show();
menuItem.setCheckable(true);
mDrawerLayout.closeDrawers();
return true;
}
});
}
这里有两个坑位需要注意:
1.设计好的彩色图标,在NavigationView中却是灰色。这里有两种办法:
- 设置属性app:itemIconTint,将item的图标设置为统一颜色。
- 在代码中调用setItemIconTintList()方法,传入null,如下:
// 这种可以显示图片原有的色彩
navigationView.setItemIconTintList(null);
2.头部布局不能响应点击的处理
在navigation_header 属性中 app:headerLayout=”@layout/navigation_header” 可以指定上部分的布局 app:menu=”@menu/drawer” 可以设置下部分菜单下面的菜单的点击事件 可以 用 setNavigationItemSelectedListener 来实现,而上面的部分 没有方法,想想也是,因为上面的部分 谷歌根本不知道你会布局什么,而下面的已经固定了。
此时,如果我希望点击头像产生事件,我首先要找到头像,而 head_iv 在布局 navigation_header 中,navigation_header 又在 NavigationView 中定义了。 所以首先要取消 app:headerLayout ,在逻辑代码中设置headview,再从headview找到head_iv,再设置点击事件。
View headview = navigationView.inflateHeaderView(R.layout.navigation_header);
ImageView avatar = (ImageView) headview.findViewById(R.id.avatar);
avatar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(tablayoutContent,"You click avatar",Snackbar.LENGTH_LONG).show();
mDrawerLayout.closeDrawers();
}
});
FloatingActionButton
floating action button 是一个负责显示界面基本操作的圆形按钮。Design library中的FloatingActionButton 实现了一个默认颜色为主题中colorAccent的悬浮操作按钮,like this:
FloatingActionButton——FAB使用非常简单,你可以指定在加强型FrameLayout里面——CoordinatorLayout,这个我们后面再将。
关于FAB的使用,你可以把它当做一个button即可。
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_done"/>
通过指定layout_gravity就可以指定它的位置。
自定义背景颜色:
app:backgroundTint="@color/mycolor"
自定义波浪颜色:
app:rippleColor="@android:color/white"
你也可以在代码中进行设置,不过设置backgroundTint稍微困难一点,因为它使用了颜色状态列表(StateList),需要按如下语句进行设置
fab.setBackgroundTintList(ColorStateList.valueOf("Your color"));
FAB有两个可选的尺寸,通过添加如下属性可以将FAB设置为迷你版本:
app:fabSize="mini"
点击事件:
// fab的点击事件
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Snackbar.make(v, "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();
}
});
注意事项
虽然这些错误在将来也许会被修复,但是我们还是先介绍几个让FAB正常工作的技巧。首先,如果你运行前面的代码,你会发现根据安卓系统版本的不同,会出现很多未料到的事情。所有这些问题似乎都和一个叫做 borderWidth的属性有关, borderWidth需要设置成0:
app:borderWidth="0dp"
另外,在lollipop以前的版本上,使用这个属性会在周围产生外边距(margin),而21+以上则不会。产生的原因和CardView上所看到的是一样的:lollipop 以前阴影是使用一个drawable来渲染的,使用的是自身的空间来绘制,而Lollipop之后阴影是由系统渲染的。CardView有一个属性可以启用compat padding。
但是浮动操作按钮却没有。不过要模拟出来耶很简单。只要根据安卓版本添加一个margin就可以了。
android:layout_margin="@dimen/fab_compat_margin"
现在只需在dimen.xml文件中定义一个属性值。
values目录下:
<dimen name="fab_compat_margin">0dp</dimen>
values-v21目录下:
<dimen name="fab_compat_margin">16dp</dimen>
OK,到现在为止,已经学习了Snackbar,TextInputLayout、TabLayout、NavigationView、FloatingActionButton这四个MD新特性布局,由于篇幅关系,和CoordinatorLayout等的重要性,咱们在下一篇接着学习Android Design Support Library使用详解(二)。关于这篇有什么不懂或错误欢迎留言指出。
参考:
Android Design Support Library使用详解
《Android 高级进阶》