本文主要是介绍Material Design 最全解析_5 UI控件,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
概述
Material Design为开发者提供了一系列的UI控件,对于开发者来说实在是福音。
今天这篇博客就记录一下UI新控件方面的知识。
先看一下大纲
UI控件
Android5.0基于Material Design,提供了很多新控件,这些控件无论在功能、体验和性能上都很出色,下面一一列举各个控件的使用方法。
SnackBar
SnackBar通过在屏幕底部展示简洁的信息,为一个操作提供了一个轻量级的反馈,并且在Snackbar中还可以包含一个操作,在同一时间内,仅且只能显示一个 Snackbar,它的显示依赖于UI,不像Toast那样可以脱离应用显示。它的用法和Toast很相似,唯一不同的就是它的第一个参数不是传入Context而是传入它所依附的父视图,但是他比Toast更强大。
(Dialog > SnackBar > Toast)
gradle
compile 'com.android.support:design:23.1.1'
最简单的提示
Snackbar.make(view, "SnackBar Demo Text", Snackbar.LENGTH_LONG).show();
设置一个Action,自带点击事件
Snackbar.make(view, "Change Text", Snackbar.LENGTH_LONG)
.setAction("OK", new View.OnClickListener() {@Overridepublic void onClick(View v) {tv.setText("New Text");}
}).show();
设置背景颜色
Snackbar sb=Snackbar.make(view, "SnackBar demo", Snackbar.LENGTH_LONG);
sb.setAction("OK", new onClickListener()());
sb.getView().setBackgroundColor(0xfff44336);
sb.show();
设置Action文字颜色
默认的Action文字颜色是ColorAccent,也可以通过api设置sb.setActionTextColor();
其他API
sb.dismiss();消失
sb.isShown();是否在显示
sb.isShownOrQueued();是否在显示或者在等待队列
sb.setText();设置文字
显示时长
LENGTH_LONG:长时间
LENGTH_SHORT:短时间
LENGTH_INDEFINITE:无限期,知道调用dismiss或者下一个SnackBar显示
注意1.SnackBar始终从底部弹出
SnackBar调用make时传进去一个View,它会顺着这个View去找父级,一直找到CoordinatorLayout或者FrameLayout,然后在它底部弹出。如果你的布局中没有包含这两个容器的一个,它就会一直找到Widnow的DecorView,效果就是在屏幕底部弹出。
看源码:
do {if(view instanceof CoordinatorLayout) {... }if(view instanceof FrameLayout) {...}} while(view != null);
了解这特性有两个用处,解决异常Bug,实现特殊需求。
Demo:
<android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="30dp"><android.support.design.widget.FloatingActionButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/ic_launcher"app:borderWidth="0dp"app:fabSize="normal" />
</android.support.design.widget.CoordinatorLayout>
注意2.悬浮按钮被snackBar遮挡
<RelaticeLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_marginBottom="30dp"><android.support.design.widget.FloatingActionButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/ic_launcher"app:borderWidth="0dp"app:fabSize="normal" />
</RelaticeLayout>
这个问题一看很棘手,其实也很简单用一下Material design库里的CoordinatorLayout即可,Java代码完全不用动。
<android.support.design.widget.CoordinatorLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_margin="30dp"><android.support.design.widget.FloatingActionButtonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:src="@mipmap/ic_launcher"app:borderWidth="0dp"app:fabSize="normal" />
</android.support.design.widget.CoordinatorLayout>
稍微总结下:
1.比toast更加好,毕竟snackbar 可以响应点击事件
2.比Dialog轻量,可以替换很多Dialog的场景
3.snackbar 同一时间有且只有一个在显示
4.snackbar 上不要有图标
5.snackbar上action 只能有一个
6.如果有悬浮按钮FloatingActionButton的话,snackbar 在弹出的时候不要覆盖这个button
7.了解为什么SnackBar是从底部弹出的
CardView
CardView曾经开始流行在Google+,后来越来越多的APP也引入了Card这样的布局方式,说到底,CardView也是一个容器布局,只是他提供了一种卡片的形式,Google所幸提供了一个CardView控件,方便大家使用这种布局,开发者可以设置大小和视图高度,圆角的角度等。
<android.support.v7.widget.CardViewandroid:id="@+id/cardview"android:layout_width="match_parent"android:layout_height="80dp"android:layout_margin="16dp"android:clickable="true"android:foreground="?android:attr/selectableItemBackground"app:cardBackgroundColor="@color/colorAccent"app:cardCornerRadius="4dp"app:cardElevation="6dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="TextView in CardView"android:textStyle="bold"android:textColor="@color/colorPrimaryDark"android:textSize="26sp" />
</android.support.v7.widget.CardView>
其实不用CardView也能实现,但是CardView做了很好的封装,只需要设置几个属性,就可以实现很好的效果,并且也减少了drawable资源,而且即便你什么都不设置,它也会设置合适的默认值。
Ps:
在低版本中设置了 CardElevation 之后 CardView 会自动留出空间供阴影显示,而 Lollipop 之后则需要手动设置 Margin 边距来预留空间,导致我在设置 Margin 在 Android 5.x 机器上调试好后,在 Kitkat 机器调试时发现边距非常大,严重地浪费了屏幕控件。因此,我们需要自定义两个dimen作为CardView的Margin值。
/res/value
/res/value-v21
android:layout_margin=”@dimen/xxx_card_margin”android:foreground=”?attr/selectableItemBackground”
这个属性会在 Lollipop 上自动加上 Ripple 效果,在旧版本则是一个变深/变亮的效果。- 让点击效果更加贴近 Material Design,要实现这个效果不难,我们只需要借助Lollipop的一个新属性
android:stateListAnimator
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"><item android:state_enabled="true" android:state_pressed="true"><objectAnimator
android:duration="@android:integer/config_shortAnimTime"android:propertyName="translationZ"android:valueTo="@dimen/touch_raise"android:valueType="floatType" /></item><item><objectAnimator
android:duration="@android:integer/config_shortAnimTime"android:propertyName="translationZ"android:valueTo="0dp"android:valueType="floatType" /></item>
</selector>
android:stateListAnimator="@anim/touch_raise"
Toolbar
Toolbar是在 Android 5.0 开始推出的一个 Material Design 风格的导航控件 ,Google 非常推荐大家使用 Toolbar 来作为Android客户端的导航栏,以此来取代之前的 Actionbar 。与 Actionbar 相比, Toolbar 明显要灵活的多。它不像 Actionbar 一样,一定要固定在Activity的顶部,而是可以放到界面的任意位置。除此之外,在设计 Toolbar 的时候,Google也留给了开发者很多可定制修改的余地,这些可定制修改的属性在API文档中都有详细介绍,如:
- 设置导航栏图标;
- 设置App的logo;
- 支持设置标题和子标题;
- 支持添加一个或多个的自定义控件;
- 支持Action Menu;
使用
前面提到 Toolbar 是在 Android 5.0 才开始加上的,Google 为了将这一设计向下兼容,自然也少不了要推出兼容版的 Toolbar 。为此,我们需要在工程中引入 appcompat-v7 的兼容包,使用 android.support.v7.widget.Toolbar 进行开发。
MXL文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><android.support.v7.widget.Toolbarandroid:id="@+id/toolbar"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/color_0176da"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Clock" /></android.support.v7.widget.Toolbar>
</LinearLayout>
MENU文件:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"><item
android:id="@id/action_search"android:icon="@mipmap/ic_search"android:title="@string/menu_search"app:showAsAction="ifRoom" /><item
android:id="@id/action_notification"android:icon="@mipmap/ic_notifications"android:title="@string/menu_notifications"app:showAsAction="ifRoom" /><item
android:id="@+id/action_item1"android:title="@string/item_01"app:showAsAction="never" /><item
android:id="@+id/action_item2"android:title="@string/item_02"app:showAsAction="never" />
</menu>
Activity:
public class ToolBarActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_tool_bar);Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);//设置导航栏图标toolbar.setLogo(R.mipmap.ic_launcher);//设置app logotoolbar.setTitle("Title");//设置主标题toolbar.setSubtitle("Subtitle");//设置子标题toolbar.setTitleTextColor(Color.rgb(250, 250, 250));//设置标题颜色toolbar.setSubtitleTextColor(Color.rgb(250, 250, 250));//设置子标题颜色toolbar.inflateMenu(R.menu.base_toolbar_menu);//设置右上角的填充菜单toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {@Overridepublic boolean onMenuItemClick(MenuItem item) {return true;}});}
}
设置更多Menu的icon:
<item name="actionOverflowButtonStyle">@style/ActionButton.Overflow.White</item>
<style name="ActionButton.Overflow.White"
parent="android:style/Widget.Material.Light.ActionButton.Overflow"><item name="android:src">@mipmap/ic_more</item>
</style>
设置返回menu的icon
toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);
通过着色改变颜色
Drawable drawable = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
drawable.setColorFilter(Color.RED, PorterDuff.Mode.SRC_IN);
toolbar.setNavigationIcon(R.mipmap.ic_drawer_home);
精卫填坑
- 坑1:在XML中设置Toolbar属性不生效
<android.support.v7.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/color_0176da"android:logo="@mipmap/ic_launcher"android:navigationIcon="@mipmap/ic_drawer_home"android:subtitle="456"android:title="123">
解决方法:在根布局中加入自定义属性的命名空间
xmlns:toolbar="http://schemas.android.com/apk/res-auto"
<android.support.v7.widget.Toolbarandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/color_0176da"toolbar:navigationIcon="@mipmap/ic_drawer_home"toolbar:logo="@mipmap/ic_launcher"toolbar:subtitle="456"toolbar:title="123">
为什么会出现这种问题呢?我猜测是因为这个控件是兼容版的控件,用 android:xxx 设置无效是的这些属性是在兼容包中,不在默认的Android SDK中,所以我们需要额外的引入。至于为什么IDE不报错,估计就是bug了吧!
坑2:menu字体颜色不能改变
在style中设置:<item name="actionMenuTextColor">#ffffff</item>
并没有用
网上有人建议直接改全局的字体颜色
在style中设置:<item name="android:textColorPrimary">#ffffff</item>
但是这样其它所有文字的默认颜色都变了,慎重慎重!坑3:ActionMode不能悬浮
解决方法:在style中设置悬浮<item name="windowActionModeOverlay">true</item>
坑4:自定义的View位于 title 、 subtitle 和 actionmenu 之间,这意味着,如果 title 和 subtitle 都在,且 actionmenu选项 太多的时候,留给自定义View的空间就越小
坑5:必须设置为没有ActionBar
使用Toolbar必须要求当前Activity没有ActionBar,方法有两种。<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">supportRequestWindowFeature(Window.FEATURE_NO_TITLE); RequestWindowFeature(Window.FEATURE_NO_TITLE);
FloatingActionButton
FloatingActionButton从名字可以看出它是一个浮动的按钮,它是一个带有阴影的圆形按钮,可以通过fabSize来改变其大小,主要负责界面的基本操作,这个按钮总体来说还是比较简单的。
默认FloatingActionButton 的背景色是应用主题的 colorAccent(其实MD中的控件主题默认基本都是应用的这个主题),可以通过app:backgroundTint 属性或者setBackgroundTintList (ColorStateList tint)方法去改变背景颜色。
- FloatingActionButton 的大小尺寸,可以用过app:fabSize 属性设置
- android:src属性改变drawable
- app:rippleColor设置点击button时候的颜色(水波纹效果)
- app:borderWidth设置 button 的边框宽度
- app:elevation设置普通状态阴影的深度(默认是 6dp)
- app:pressedTranslationZ设置点击状态的阴影深度(默认是 12dp)
<android.support.design.widget.FloatingActionButtonandroid:id="@+id/fab_search"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:layout_margin="20dp"android:clickable="true"android:src="@android:drawable/ic_dialog_email"app:borderWidth="1dp"app:fabSize="normal"app:rippleColor="#0000ff"app:elevation="3dp"app:pressedTranslationZ="6dp"/>
NavigationView
NavigationView可以和DrawerLayout一起结合使用
代码:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:id="@+id/drawer_layout"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"><android.support.design.widget.NavigationViewandroid:id="@+id/navigation_view"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_gravity="start"app:headerLayout="@layout/navigation_header"app:menu="@menu/drawer" />
</android.support.v4.widget.DrawerLayout>
<LinearLayout 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="192dp"android:background="?attr/colorPrimaryDark"android:gravity="center"android:orientation="vertical"android:padding="16dp"android:theme="@style/ThemeOverlay.AppCompat.Dark"><ImageView
android:layout_width="72dp"android:layout_height="72dp"android:src="@mipmap/profile"app:border_color="@color/primary_light"app:border_width="2dp" /><TextView
android:layout_marginTop="10dp"android:textSize="18sp"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="APP开发者"/>
</LinearLayout>
和普通的menu比,就多了单选属性
<menu xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"tools:context=".MainActivity"><group android:checkableBehavior="single"><item
android:id="@+id/navigation_item_example"android:icon="@drawable/ic_favorite"android:title="@string/navigation_example" /><item
android:id="@+id/navigation_item_blog"android:icon="@drawable/ic_favorite"android:title="@string/navigation_my_blog" /><item
android:id="@+id/navigation_item_about"android:icon="@drawable/ic_favorite"android:title="@string/navigation_about" /></group>
</menu>
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {@Overridepublic boolean onNavigationItemSelected(MenuItem menuItem) {return true;}});
在Material Design中,Navigation drawer导航抽屉,被设计用于应用导航,提供了一种通用的导航方式,体现了设计的一致性。
而NavigationView的典型用途就是配合之前v4包的DrawerLayout,作为其中的Drawer部分,即导航菜单的本体部分。NavigationView是一个导航菜单框架,使用menu资源填充数据,使我们可以更简单高效的实现导航菜单。它提供了不错的默认样式、选中项高亮、分组单选、分组子标题、以及可选的Header。
TextInputLayout
使用过EditText的同学肯定知道,有一个叫hint的属性,它可以提示用户此处应该输入什么内容,然而当用户输入真实内容之后,hint的提示内容就消失了,用户的体验效果是十分不好的,TextInputLayout的出现解决了这个问题。
初始状态
点击输入内容
当用户在输入的时候hint的内容就会跑到输入内容的上边去,并且是以动画的形式,体验非常好。其中TextInputLayout中字体的颜色是style文件中的colorAccent。
看下代码:
<android.support.design.widget.TextInputLayoutandroid:id="@+id/til"android:layout_width="match_parent"android:layout_height="wrap_content"app:errorEnabled="true"><EditTextandroid:id="@+id/et"android:layout_width="match_parent"android:layout_height="wrap_content"android:hint="Password"/>
</android.support.design.widget.TextInputLayout>textLayout = (TextInputLayout)findViewById(R.id.til);
textLayout.setHint("Password");
非常简单的使用方法,只是在EditText外再套一层TextInputLayout。
错误提示
TextInputLayout还有一个挺不错的设计,就是错误提示,当用户输入内容不正确时,可以在底部弹出一个错误提示。要使用错误提示,需要先设置errorEnable为true。
textInputLayout.setErrorEnabled(true);
app:errorEnable=”true”
然后调用setError(“输入错误”);
设置样式
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"><item name="colorAccent">#3498db</item>
</style>
TabLayout
我们在使用viewpager的时候,经常会使用TabPageIndicator来与其配合。达到很漂亮的滑动效果。但是TabPageIndicator是第三方的,而且比较老了,当然了现在很多大神都已经开始自己写TabPageIndicator来满足需求,在2015年的google大会上,新的Android Support Design库就包含了TabLayout,它可以实现TabPageIndicator的效果,而且兼容性非常好,最低可以兼容到2.2,32个赞不能再少了。
XML代码
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" android:orientation="vertical"> <android.support.design.widget.TabLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/titleBlue"app:tabIndicatorColor="@color/white"app:tabSelectedTextColor="@color/gray"app:tabTextColor="@color/white" /><android.support.v4.view.ViewPagerandroid:layout_width="fill_parent"android:layout_height="0dp"android:layout_weight="1" />
</LinearLayout>
java代码
TabLayout tabLayout;
tabLayout = (TabLayout)view.findViewById(R.id.tab_FindFragment_title);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setTabMode(TabLayout.MODE_FIXED);
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.addTab(tabLayout.newTab().setText("Tab3"));
tabLayout.addTab(tabLayout.newTab().setText("Tab4"));viewPager.stAdapter(adapter);
tabLayout.setViewPager(viewPager);
//tabLayout.setupWithViewPager(viewPager);
属性
tabLayout.setTabMode(TabLayout.MODE_FIXED);
MODE_FIXED:固定模式,每一个Tab等宽,不管多少都显示全部。
MODE_SCROLLABLE:滚动模式,适合多Tab,长短不一
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
GRAVITY_CENTER:居中显示
GRAVITY_FILL:充满整个宽度
setIcon: tab.setIcon(R.drawable.ic_1);
要icon横向显示,可以使用setCustomView
tab.setCustomView(getCustomView(index));
精卫填坑
tabLayout.setupWithViewPager(viewPager);
看源码,这个方法中调用了setTabsFromPagerAdapter(adapter);
public void setTabsFromPagerAdapter(@NonNull PagerAdapter adapter) {removeAllTabs();for (int i = 0, count = adapter.getCount(); i < count; i++) {addTab(newTab().setText(adapter.getPageTitle(i)));}
}
removeAllTabs()
这个就是说把前面所有tablayout添加的view都删掉。也就是说在之前不管怎么处理view都被干掉。然后设置为PagerAdapter返回的title。
tabLayout.addTab(tab1);
tabLayout.addTab(tab2);
tabLayout.addTab(tab3);
tabLayout.addTab(tab4);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setupWithViewPager(viewPager);
tabLayout.addTab(tab1);
tabLayout.addTab(tab2);
tabLayout.addTab(tab3);
tabLayout.addTab(tab4);
通过Adapter返回title
@Override
public CharSequence getPageTitle(int position) {return “xxx”;
}
Notification
Notification作为一个时间触发性的交互提示接口,让我们获得消息的时候,在状态栏,锁屏界面显示相应的消息
Google在Android5.X中,又进一步的改进了通知栏,优化了Notification,在5.X设备上一个标准的通知是这样的,长按会显示消息的来源。
- 基本的Notification
顶部显示横条- 折叠式Notification
下拉时显示扩展模式,高度变高- 悬挂式Notification
在顶部悬浮显示,提示性更强- 显示等级的Notification
VISIBILITY_PUBLIC 只有在没有锁屏时会显示通知
VISIBILITY_PRIVATE 任何情况都会显示通知
VISIBILITY_SECRET 在安全锁和没有锁屏的情况下显示通知
AppbarLayout、CollapsingToolbarLayout、NestedScrollView、CoordinatorLayout
这几个控件就不一一说了,把他们合在一起写一个Demo一看便懂。Demo效果还是很明显的。
下载链接:http://download.csdn.net/detail/u011002668/9583550
RecyclerView
这个控件是Material Design新增控件中最复杂的,但是可能也是大家最熟悉的,因为很多人都开始使用它来替代ListView了,关于RecyclerView,张鸿洋有一片博客说的非常好了,很全面,这里我就不再说了,直接把链接发出来。
http://download.csdn.net/detail/u011002668/9583550
总结
到这里,Material Design的UI控件已经基本讲完了,下一篇也是最后一篇,会讲一下Material动画,相信也有很多东西会让大家眼前一亮。
本期节目就到这里,感谢大家收看,我们下期再见~
这篇关于Material Design 最全解析_5 UI控件的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!