[转载请注明出处:http://blog.csdn.net/listeners_Gao/article/details/52886162 —By ListenerGao]
前言
谷歌在2015年I/O大会上发布了Android M的新版本.在这次的I/O大会上,谷歌对Android并没有做很大的改变,主要完善之前的Android L版本.不过这次谷歌在继Material Design风格之后,做了很多风格上的兼容,并推出了Android Design Support Library库,全面支持Material Design设计风格的UI效果.该库包含了FloatingActionButton,TextInputLayout,Snackbar,TabLayout,NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout八个新控件.由于篇幅的原因,我们先来学习一下前四个的使用.后续会继续完成其余控件的使用.
使用
需要导入Android Design Support Library库,该库支持Android 2.1以上设备.在build.gradle(moudle:app)中添加依赖:compile 'com.android.support:design:24.2.1'
版本号可自己匹配.
FloatingActionButton
效果图:
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="@drawable/ic_favorite"
android:layout_margin="10dp"
app:backgroundTint="@color/colorPrimary"
app:elevation="4dp"
app:pressedTranslationZ="8dp"
app:fabSize="normal"
app:rippleColor="@color/colorPrimaryDark"
app:useCompatPadding="false" />
注意:
设置FloatingActionButton的背景颜色时使用:app:backgroundTint,默认为 Theme 主题中的 “colorAccent”的颜色;如果使用android:backgroundTint运行时,则会报解析Xml异常.
设置FloatingActionButton的大小,通过app:fabSize属性来设置,有三种格式:auto(基于窗口的大小而自动适应),normal(正常大小的按钮),mini(迷你大小的按钮).这里设置layout_width和layout_height貌似没有什么效果,FloatingActionButton的大小由fabSize属性来决定.可当你把宽和高设置成match_parent时,FloatingActionButton的大小会充满父窗体,大小虽然改变了,但这样的设置在开发中貌似没一点卵用.
app:elevation :设置 FloatingActionButton 阴影的深度,默认有阴影.
app:pressedTranslationZ :设置 FloatingActionButton 点击时阴影的大小.
app:rippleColor :设置 FloatingActionButton 点击时的颜色,也就是设置上面属性后,阴影的颜色.
app:useCompatPadding :设置是否启用compat的填充.
src - 设置FAB的图标,Google建议符合Design设计的该图标大小为24dp.
app:layout_anchor - 设置FAB的锚点,即以哪个控件为参照点设置位置.
app:layout_anchorGravity - 设置FAB相对锚点的位置,值有 bottom、center、right、left、top等.
以上在Xml布局中设置的属性,在代码中同样可以设置.
Snackbar
简介: Snackbar用于展示一条简短的消息给用户,该消息在很多的时间内会消失.该消息只是给用户一个提示,用户不需要去操作.例如:当我们发送一条Email时,告诉用户该Email发送的状态.Snackbar和Toast很像,只不过Toast是在屏幕中心弹出,而Snackbar是在屏幕底部弹出.
使用:代码中使用
//得到Snackbar对象 final Snackbar snackbar = Snackbar.make(coordinatorLayout, "我是Snackbar...", Snackbar.LENGTH_LONG); //设置Snackbar背景 snackbar.getView().setBackgroundResource(R.color.colorPrimary); snackbar.show(); //显示带Action的Snackbar snackbar.setAction("取消", new View.OnClickListener() { @Override public void onClick(View v) { //关闭Snackbar snackbar.dismiss(); } });
常用方法:
- make() 方法,生成Snackbar消息对象,第一个参数为View对象,Snackbar 会试着寻找一个父 View 来 hold 这个 View。Snackbar 将遍历整个 View tree 来寻找一个合适的父 View,它可能是一个 coordinatorLayout 也可能是 window decor’s content view,随便哪一个都行.后面的两个参数和Toast一致.
- setDuration() 方法:设置显示持续时间.
- setAction() 方法:设置 Action,第一个参数会作为按钮(Actiong)的文本,第二个参数是按钮的点击事件.
- setCallback() 方法:Snackbar 的显示和消失会回调 Snackbar.Callback的 onDismissed()和 onShown()方法.
- getView():获取 Snackbar 的 View,进而可以定制Snackbar.
注意:
- 谷歌其实更建议在CoordinatorLayout(不要着急,后面会细说)布局中使用Snackbar(make()方法中传入的View),当用户滑动屏幕时,可以使Snackbar消失.
- 当然,如果你只是想在底部弹出提示消息,那么make()方法中传入的任意的View即可.
- 还有就是当你点击FloatingActionButton时,想弹出Snackbar,同时又想避免Snackbar遮盖住FloatingActionButton,这时,你应该使用CoordinatorLayout来协调各个View之间的动画效果.
效果图:设置点击FloatingActionButton的点击事件,点击弹出Snackbar.
TextInputLayout
简介: TextInputLayout的出现是Google为EditText提供的浮动标签,使其更符合Material Design的风格.TextInputLayout继承LinearLayout,它只是一个容器,不过该容器下只接收一个元素,子元素就是一个EditText元素.这样就为EditText提供了一个带有动画效果的提示标签,同时也可以处理错误信息,将错误信息提示在EditText的下方.
使用:
布局:
<android.support.design.widget.TextInputLayout android:id="@+id/til_username" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="20dp"> <!--这里可以直接使用EditText--> <android.support.design.widget.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Username" /> </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_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="10dp"> <android.support.design.widget.TextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="Password" android:inputType="textPassword" /> </android.support.design.widget.TextInputLayout>
代码:
//初始化TextInputLayout(代码中我使用了ButterKnife注解,这里就不贴出来了) //得到EditText对象 final EditText userEditText = tilUsername.getEditText(); final EditText pwdEditText = tilPassword.getEditText(); //设置hint提示,也可直接在xml中设置(个人感觉如果在布局中已经设置了hint,代码中就不必在设置了.) //userEditText.setHint("Username"); //pwdEditText.setHint("Password"); //EditText添加文本变化监听 userEditText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { Log.d(TAG, "beforeTextChanged执行了....s = " + s + "---start = " + start + "---count = " + count + "---after = " + after); } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { Log.d(TAG, "onTextChanged执行了....s = " + s + "---start = " + start + "---count = " + count + "---before = " + before); if (s.length() > 7) { tilUsername.setErrorEnabled(true);//设置是否打开错误提示 tilUsername.setError("用户名长度不能超过8个");//设置错误提示的信息 } else { tilUsername.setErrorEnabled(false); } } @Override public void afterTextChanged(Editable s) { Log.d(TAG, "afterTextChanged执行了....s = " + s); } }); pwdEditText.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() < 6) { tilPassword.setErrorEnabled(true); tilPassword.setError("密码长度不能小于6个"); } else { tilPassword.setErrorEnabled(false); } } @Override public void afterTextChanged(Editable s) { } });
注意:代码里注释已经很详细了,相信你一看就能明白.这里提一点:就是浮动标签字体的颜色默认是你设置主题时的颜色.
设置主题的颜色就是EditText浮动标签提示信息的颜色:
<item name="colorAccent">@color/colorAccent</item>
效果图:这里模拟登录界面。并对用户名长度是否超过8个,密码长度是否小于6个做了判断。
TabLayout
- 简介: TabLayout提供了一个水平布局显示标签,主要用来做选显卡切换这一类效果的控件。例如:网易新闻客户端的Tab。Github上也有很多类似效果的开源控件,只是这次谷歌把它官方化了,更方便开发者使用。
简单TabLayout效果图:
使用:
xml:
<android.support.design.widget.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabIndicatorColor="@android:color/holo_blue_bright" //Tab指示器下标的颜色 app:tabSelectedTextColor="@android:color/holo_blue_bright" //Tab被选中字体的颜色 app:tabTextColor="@android:color/black"> //Tab未被选中字体的颜色 </android.support.design.widget.TabLayout>
代码:
//添加8个Tab标签,并设置第一个Tab标签为选中状态. tabLayout.addTab(tabLayout.newTab().setText("Tab 1"),true); 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.addTab(tabLayout.newTab().setText("Tab 7")); tabLayout.addTab(tabLayout.newTab().setText("Tab 8")); //设置Tab的模式为可滑动,当tab标签超过屏幕宽度时,可以滑动. tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE);
这里只是简单使用TabLayout完成Tabs选项卡,一般情况下TabLayout+ViewPager相结合使用,这样的使用场景会更多一点,也能发挥出TabLayout的优势。接下来使用TabLayout+ViewPager完成一个小Demo。
效果图:(自定义TabLayout样式+ViewPager使用)
使用:首先我们在Style中自定义TabLayout的样式,在布局中使用时引入自定义的TabLayout样式.添加ViewPager,每个页面是一个Fragment,并且实现联动效果,下面直接看代码:
自定义TabLayout样式:
<!-- 自定义 TabLayout 样式 --> <style name="CustomTabLayout" parent="Widget.Design.TabLayout"> <item name="paddingEnd">10dp</item> <item name="paddingStart">10dp</item> <item name="tabBackground">@color/colorPrimary</item> <item name="tabContentStart">10dp</item> <item name="tabGravity">center</item> <item name="tabIndicatorColor">#999900</item> <item name="tabIndicatorHeight">6dp</item> <item name="tabMaxWidth">@dimen/tab_max_width</item> <item name="tabMinWidth">@dimen/tab_min_width</item> <item name="tabMode">scrollable</item> <item name="tabPaddingBottom">2dp</item> <item name="tabPaddingEnd">10dp</item> <item name="tabPaddingStart">10dp</item> <item name="tabPaddingTop">15dp</item> <item name="tabSelectedTextColor">#ffcc00</item> <item name="tabTextAppearance">@style/CustomTabTextAppearance</item> <item name="tabTextColor">#000066</item> </style> <!-- 自定义 TabText 的外观 --> <style name="CustomTabTextAppearance" parent="TextAppearance.Design.Tab"> <item name="android:textSize">14sp</item> <item name="android:textColor">#006600</item> <item name="textAllCaps">false</item> </style>
页面布局:
<?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:id="@+id/activity_tab_layout_view_pager" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.listenergao.mytest.activity.TabLayoutViewPagerActivity"> <include layout="@layout/toolbar_layout" /> <android.support.design.widget.TabLayout android:id="@+id/tab_layout" style="@style/CustomTabLayout" android:layout_width="match_parent" android:layout_height="wrap_content"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </LinearLayout>
页面代码:(Activity页面)
package com.listenergao.mytest.activity; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.view.ViewPager; import android.support.v7.widget.Toolbar; import android.widget.LinearLayout; import com.listenergao.mytest.R; import com.listenergao.mytest.data.TabFragmentAdapter; import com.listenergao.mytest.fragment.TabFragment; import java.util.ArrayList; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; /** * TabLayout+ViewPager示例 * * @author By ListenerGao * create at 2016/10/14 18:52 */ public class TabLayoutViewPagerActivity extends BaseActivity { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.tab_layout) TabLayout tabLayout; @BindView(R.id.viewpager) ViewPager viewpager; @BindView(R.id.activity_tab_layout_view_pager) LinearLayout activityTabLayoutViewPager; private List<String> mTabList; private List<Fragment> mTabFragments; @Override protected int getLayoutResId() { return R.layout.activity_tab_layout_view_pager; } @Override protected void initView() { ButterKnife.bind(this); toolbar.setTitle("TabLayout+ViewPager"); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); } @Override protected void initData() { mTabList = initTabList(); initTabLayout(mTabList); mTabFragments = initFragments(mTabList); TabFragmentAdapter adapter = new TabFragmentAdapter(getSupportFragmentManager(),mTabFragments,mTabList); viewpager.setAdapter(adapter); //将TabLayout与ViewPager关联起来(注意:该行代码需在ViewPager设置Adapter之后调用) tabLayout.setupWithViewPager(viewpager); //为Tabs设置适配器 tabLayout.setTabsFromPagerAdapter(adapter); } /** * 初始化Tab标签数据 * * @return */ private List<String> initTabList() { List<String> tabList = new ArrayList<>(); for (int i = 0; i < 8; i++) { tabList.add("TAB " + i); } return tabList; } /** * 初始化TabLayout * * @param list */ private void initTabLayout(List<String> list) { for (int i = 0; i < list.size(); i++) { if (i == 0) tabLayout.addTab(tabLayout.newTab().setText(list.get(i)), true); else tabLayout.addTab(tabLayout.newTab().setText(list.get(i))); } //设置TabLayout的模式为可滑动 tabLayout.setTabMode(TabLayout.MODE_SCROLLABLE); } /** * 初始化Tab标签对应的Fragment * * @param list 标签集合数据 * @return */ public List<Fragment> initFragments(List<String> list) { List<Fragment> mTabFragments = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { Fragment tabFragment = new TabFragment(); Bundle bundle = new Bundle(); bundle.putString("Content", list.get(i)); tabFragment.setArguments(bundle); mTabFragments.add(tabFragment); } return mTabFragments; } }
Viewpager适配器:(这里继承的是FragmentStatePagerAdapter,因为可能有很多个Tab标签页面(Fragment).这里不细说,可以自行google.)
package com.listenergao.mytest.data; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import java.util.List; /** * ViewPager的适配器 * * @author By ListenerGao * Create at 2016/10/15 16:36 */ public class TabFragmentAdapter extends FragmentStatePagerAdapter { private List<Fragment> mFragments; private List<String> mTabTitles; public TabFragmentAdapter(FragmentManager fm, List<Fragment> fragments,List<String> tabTitles) { super(fm); this.mFragments = fragments; this.mTabTitles = tabTitles; } @Override public Fragment getItem(int position) { return mFragments.get(position); } @Override public int getCount() { return mFragments.size(); } //注意:需要重写此方法,从标签集合中获取到title,否则标签上的title则不会显示. @Override public CharSequence getPageTitle(int position) { return mTabTitles.get(position); } }
Tab标签对应的Fragment页面:
package com.listenergao.mytest.fragment; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.listenergao.mytest.R; import butterknife.BindView; import butterknife.ButterKnife; /** * Tab标签对应的页面 * * @author By ListenerGao * Create at 2016/10/15 16:53 */ public class TabFragment extends Fragment { @BindView(R.id.tv_content) TextView tvContent; private View view; private String content; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { Bundle bundle = getArguments(); content = bundle.getString("Content"); } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment view = inflater.inflate(R.layout.fragment_tab, container, false); ButterKnife.bind(this, view); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); tvContent.setText(content); } }
常用方法:
- 1,addTab(TabLayout.Tab tab, int position, boolean setSelected) 增加选项卡到 layout中,这是一个重载方法.第一个参数是Tab对象,通过Tablayout.newTab()创建;第二个参数是插入Tab的位置;最后一个参数是当前Tab是否为选中状态.
- 2,newTab() 新建个 tab.
- 3,setTabMode(),设置 Mode,有两种值:TabLayout.MODE_SCROLLABLE和TabLayout.MODE_FIXED分别表示当tab的内容超过屏幕宽度是否支持横向水平滑动,第一种支持滑动,第二种不支持,默认不支持水平滑动.如果你添加的Tab很少的话,你应该把Tab的mode设置成MODE_FIXED,否则可能会出现Tab标签不会占满屏幕的宽度.
- 4,setOnTabSelectedListener(TabLayout.OnTabSelectedListener onTabSelectedListener) 为每个 tab 增加选择监听器.
- 5,setScrollPosition(int position, float positionOffset, boolean updateSelectedText) 设置Tab滚动到的位置.
- 6,setTabGravity(int gravity) 设置 Gravity.
- 7,setTabTextColors(ColorStateList textColor) 设置 tab 中文本的颜色.
- 8,setTabTextColors(int normalColor, int selectedColor) 设置 tab 中文本的颜色 默认 选中的颜色.
- 9,setTabsFromPagerAdapter(PagerAdapter adapter) 将TabLayout与ViewPager关联,当PageAdapter更新时,TabLayout会自动更新.(注意:该方法已过时)
- 10,setupWithViewPager(ViewPager viewPager) 设置Tablayout和ViewPager实现联动效果.
- 11,getTabAt(int index) 得到选项卡.
- 12,getTabCount() 得到选项卡的总个数.
- 13,getTabGravity() 得到 tab 的 Gravity.
- 14,getTabMode() 得到 tab 的模式.
- 15,getTabTextColors() 得到 tab 中文本的颜色.
由于篇幅原因,NavigationView,CoordinatorLayout,AppBarLayout,CollapsingToolbarLayout会在下篇文章中介绍.
源码地址:(该功能是在我一个练手项目中写的)