Material Design for Android
来源:互联网 发布:js 数组 sort 编辑:程序博客网 时间:2024/05/19 00:13
Material 主题
想要使用Material Design,就需要先设置主题,系统自带主题
- @android:style/Theme.Material(深色版本)
- @android:style/Theme.Material.Light(浅色版本)
- @android:style/Theme.Material.Light.DarkActionBar
常用的样式属性:
<style name="RedTheme" parent="android:Theme.Material"> <!-- 状态栏颜色,会被statusBarColor效果覆盖--> <item name="android:colorPrimaryDark">@color/status_red</item> <!-- 状态栏颜色,继承自colorPrimaryDark --> <item name="android:statusBarColor">@color/status_red</item> <!-- actionBar颜色 --> <item name="android:colorPrimary">@color/action_red</item> <!-- 背景颜色 --> <item name="android:windowBackground">@color/window_bg_red</item> <!-- 底部栏颜色 --> <item name="android:navigationBarColor">@color/navigation_red</item> <!-- ListView的分割线颜色,switch滑动区域色--> <item name="android:colorForeground">@color/fg_red</item> <!-- popMenu的背景色 --> <item name="android:colorBackground">@color/bg_red</item> <!-- 控件默认颜色 ,效果会被colorControlActivated取代 --> <item name="android:colorAccent">@color/control_activated_red</item> <!-- 控件默认时颜色 --> <item name="android:colorControlNormal">@color/control_normal_red</item> <!-- 控件按压时颜色,会影响水波纹效果,继承自colorAccent --> <item name="android:colorControlHighlight">@color/control_highlight_red</item> <!-- 控件选中时颜色 --> <item name="android:colorControlActivated">@color/control_activated_red</item> <!-- Button的默认背景 --> <item name="android:colorButtonNormal">@color/button_normal_red</item> <!-- Button,textView的文字颜色 --> <item name="android:textColor">@color/white_text</item> <!-- RadioButton checkbox等控件的文字 --> <item name="android:textColorPrimaryDisableOnly">@color/white_text</item> <!-- actionBar的标题文字颜色 --> <item name="android:textColorPrimary">@color/white_text</item></style>
定义阴影与裁剪视图
Z轴属性
视图的 Z 值包含两个组件:
- 高度:静态组件。
- 转换:用于动画的动态组件。 Z = elevation + translationZ
android:elevation //静态Z轴的高度。相对于父控件的高度android:translationZ //Z轴偏移的高度。
Z轴的大小会决定视图的遮盖关系,Z值大的View会优先显示于UI中.
你可以在代码中使用 View.setElevation()
和View.setTranslationZ()
来设置Z的大小,在属性动画中也提供了关于Z轴的方法, ViewPropertyAnimator.z()
与ViewPropertyAnimator.translationZ()
裁剪视图
将可裁剪的view裁剪成各种形状
holder.profileImageView.setOutlineProvider(new ViewOutlineProvider() { @Override public void getOutline(View view, Outline outline) { int r = Math.min(view.getHeight(), view.getWidth()); outline.setRoundRect(0, 0, r, r, r / 2); } }); holder.profileImageView.setClipToOutline(true);
上面这句话就可以很简单地设置imageview为圆形,但是这种方式的绘制成本是很高的,所以这里只是演示作用
调色板Palette
// Synchronous Palette p = Palette.from(bitmap).generate(); // Asynchronous Palette.from(bitmap).generate(new PaletteAsyncListener() { public void onGenerated(Palette p) { // Use generated instance } });
根据图片的颜色分配来设置statusBar的颜色值:
// Set the background and text colors of a toolbar given a// bitmap image to matchpublic void setToolbarColor(Bitmap bitmap) { // Generate the palette and get the vibrant swatch // See the createPaletteSync() and checkVibrantSwatch() methods // from the code snippets above Palette p = createPaletteSync(bitmap); Palette.Swatch vibrantSwatch = checkVibrantSwatch(p); // Set the toolbar background and text colors Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setBackgroundColor(vibrantSwatch.getRgb()); toolbar.setTitleTextColor(vibrantSwatch.getTitleTextColor());}
触摸反馈
- ?android:attr/selectableItemBackground 指定有界的波纹。
- ?android:attr/selectableItemBackgroundBorderless 指定越过视图边界的波纹。 也就是波纹动画会涉及到父容器.
如果要改变默认触摸反馈颜色,请使用主题的 android:colorControlHighlight 属性
自定义波纹颜色:
<?xml version="1.0" encoding="utf-8"?><ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="#ffff0000"></ripple>
揭露效果
效果:
void enterReveal(final View targetView) { //获取view的中心点 int cx = targetView.getMeasuredWidth() / 2; int cy = targetView.getMeasuredHeight() / 2; int finalRadius = Math.max(targetView.getWidth(), targetView.getHeight()) / 2; Animator anim = ViewAnimationUtils.createCircularReveal(targetView, cx, cy, 0, finalRadius); targetView.setVisibility(View.VISIBLE); anim.start(); } void exitReveal(final View targetView) { int cx = targetView.getMeasuredWidth() / 2; int cy = targetView.getMeasuredHeight() / 2; int initialRadius = targetView.getWidth() / 2; Animator anim = ViewAnimationUtils.createCircularReveal(targetView, cx, cy, initialRadius, 0); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); targetView.setVisibility(View.INVISIBLE); } }); anim.start(); }
定制动画
指定定制转换
开启指定定制转换两种方式
- 在主题文件中设置<item name="android:windowContentTransitions">true</item>
- 在代码中设置getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
以及其他效果同样可以在theme中定义
<style name="BaseAppTheme" parent="android:Theme.Material"> <!-- enable window content transitions --> <item name="android:windowContentTransitions">true</item> <!-- specify enter and exit transitions --> <item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item> <!-- specify shared element transitions --> <item name="android:windowSharedElementEnterTransition"> @transition/change_image_transform</item> <item name="android:windowSharedElementExitTransition"> @transition/change_image_transform</item></style>
change_image_transform 转换定义如下:
<!-- res/transition/change_image_transform.xml --><!-- (see also Shared Transitions below) --><transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <changeImageTransform/></transitionSet>
代码中开启:
// inside your activity (if you did not enable transitions in your theme)getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);// set an exit transitiongetWindow().setExitTransition(new Explode());
并在startActivity时设置:
//没有共享元素 ActivityOptions options=ActivityOptions.makeSceneTransitionAnimation(this); //1个共享元素 ActivityOptions options = ActivityOptions .makeSceneTransitionAnimation(this, sharedElementView, "sharedElementName"); //多个共享元素 ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, Pair.create(sharedElementView1, "sharedElementName1"), Pair.create(sharedElementView2, "sharedElementName2")); // 启动Activity startActivity(intent,ActivityOptionsCompat. makeSceneTransitionAnimation(MainActivity.this).toBundle());
Android默认提供了3中场景转换:
- Explode
- Fade
- Slide
这里演示Slide效果,这是默认new Slide()的效果:
可以看到toolbar都一起下滑了,这时候需要自定义.
在res下新建transition文件夹,然后建立slide.xml:
<?xml version="1.0" encoding="utf-8"?><slide xmlns:android="http://schemas.android.com/apk/res/android" android:slideEdge="right" android:duration="1000"> <targets> <!-- if using a custom Toolbar container, specify the ID of the AppBarLayout --> <target android:excludeId="@id/app_bar_layout" /> <target android:excludeId="@android:id/statusBarBackground"/> <target android:excludeId="@android:id/navigationBarBackground"/> </targets></slide>
或者设置组合动画:
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android"> <fade android:duration="300" android:fadingMode="fade_in_out"> <targets> <!-- if using a custom Toolbar container, specify the ID of the AppBarLayout --> <target android:excludeId="@android:id/statusBarBackground"/> <target android:excludeId="@android:id/navigationBarBackground"/> </targets> </fade> <slide xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:slideEdge="bottom"> <targets> <!-- if using a custom Toolbar container, specify the ID of the AppBarLayout --> <target android:excludeId="@id/app_bar_layout"/> <target android:excludeId="@android:id/statusBarBackground"/> <target android:excludeId="@android:id/navigationBarBackground"/> </targets> </slide></transitionSet>
代码中设置:
getWindow().setExitTransition(TransitionInflater.from(this). inflateTransition(R.transition.slide));
中android:excludeId的作用就是排除这些ID,让他们不会有这个转场效果
自定义效果:
共享元素
也就是上面图中图片的转场效果
1.在两个acitvity的布局中设置`android:transitionName=”profile”,要保证名字一样
2.
Intent intent = new Intent(MainActivity.this, TransitionActivity.class); TransitionActivity.imageUrls = imageUrls[position]; Pair<View, String> p1 = Pair.create((View) holder.profileImageView, "profile"); //如果是多个效果则再设置Pair ActivityOptionsCompat options = ActivityOptionsCompat. makeSceneTransitionAnimation(MainActivity.this, p1); startActivity(intent, options.toBundle());
其次你需要在activity结束的时候设置结束动画:
@Overridepublic boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { // Respond to the action bar's Up/Home button case android.R.id.home: supportFinishAfterTransition(); return true; } return super.onOptionsItemSelected(item);}
在fragment中使用共享元素
// Inflate transitions to apply Transition changeTransform = TransitionInflater.from(this). inflateTransition(R.transition.change_image_transform); Transition explodeTransform = TransitionInflater.from(this). inflateTransition(android.R.transition.explode); // Setup exit transition on first fragment fragmentOne.setSharedElementReturnTransition(changeTransform); fragmentOne.setExitTransition(explodeTransform); // Setup enter transition on second fragment fragmentTwo.setSharedElementEnterTransition(changeTransform); fragmentTwo.setEnterTransition(explodeTransform); // Find the shared element (in Fragment A) ImageView ivProfile = (ImageView) findViewById(R.id.ivProfile); // Add second fragment by replacing first FragmentTransaction ft = getFragmentManager().beginTransaction() .replace(R.id.container, fragmentTwo) .addToBackStack("transaction") .addSharedElement(ivProfile, "profile"); // Apply the transaction ft.commit();
为视图状态改变添加动画
StateListAnimator 类别让您能够定义视图状态改变时运行的动画
在xml中定义:
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="true"> <set> <objectAnimator android:duration="@android:integer/config_shortAnimTime" android:propertyName="translationY" android:valueTo="50dp" android:valueType="floatType"/> </set> </item> <item android:state_pressed="false"> <set> <objectAnimator android:duration="@android:integer/config_shortAnimTime" android:propertyName="translationY" android:valueTo="0dp" android:valueType="floatType"/> </set> </item></selector>
在view中设置 android:stateListAnimator="@drawable/statelist"
注意在imageView中要设置 android:clickable="true"
我这里是设置点击的时候将view的Y轴移动50dp,松手的时候回归原位.效果图如下:
代码中使用AnimationInflater.loadStateListAnimator()方法,并以 View.setStateListAnimator() 方法将设置动画.在Material Design主题中,Button默认会有一个Z轴动画,便是我们看到的点击出现阴影,如果你想取消该效果,则设置android:stateListAnimator
属性为@null
视图层级动画
这里顺便提一下场景,早在4.4的时候,我们可以通过场景的动画做很多特效,使用TransitionManager.beginDelayedTransition
方法
代码如下:
int selected = gridLayout.indexOfChild(v); if(selected > 0) { View cur = gridLayout.getChildAt(0); int currentId = cur.getId(); int selectedId = v.getId(); TransitionManager.beginDelayedTransition(gridLayout, new ChangeBounds()); gridLayout.removeView(v); gridLayout.addView(v, 0); GridLayout.LayoutParams params = (GridLayout.LayoutParams)cur.getLayoutParams(); cur.setLayoutParams(v.getLayoutParams()); v.setLayoutParams(params); if(currentId == R.id.item_2c || (currentId == R.id.item_2b && selectedId == R.id.item_2c)) { gridLayout.removeView(cur); gridLayout.addView(cur); } }
TransitionManager的基本流程:
- 捕获启动状态
- 进行布局的变化
- 捕获结束状态
- 运行动画
可以自定义的类型:
- slide (entering/exiting from an edge)
- changeBounds (resizing or moving)
- fade (changing visibility)
- changeClipBounds (adjusting boundary where view is cut off)
- changeTransform (adjusting scale/rotation)
- changeImageTransform (adjusting size, shape, scaleType of an image)
- pathMotion (allows movement along a path)
- explode (slide in some direction depending on epicenter)
- recolor (change background or next color)
详情可参考 https://guides.codepath.com/android/View-Hierarchy-Animations#overview
Material Design控件
ToolBar
主题中一些常用属性:
<style name="ToolbarTheme" parent="AppTheme"> <!-- 设置 toolbar 溢出菜单的文字的颜色 --> <item name="android:textColor">@color/colorAccent</item> <!-- 设置toolbar 溢出菜单的字体大小--> <item name="android:textSize">18sp</item> <!-- 设置 显示在tooBar上菜单文字的颜色 --> <item name="actionMenuTextColor">@color/colorAccent</item> <!-- 设置 toolBar溢出菜单颜色 (三个点那个图标) --> <item name="android:textColorSecondary">@color/md_white_1000</item> <!--<item name="actionOverflowButtonStyle">@style/over_flow</item>--> <!--<item name="actionOverflowMenuStyle">@style/over_flow_popList</item>--> </style> <!--修改溢出菜单图标 --> <style name="over_flow" parent="Base.Widget.AppCompat.ActionButton.Overflow"> <item name="srcCompat">@mipmap/ic_launcher</item> <item name="android:background">?attr/actionBarItemBackground</item> <item name="android:contentDescription">@string/abc_action_menu_overflow_description</item> <item name="android:minWidth">@dimen/abc_action_button_min_width_overflow_material</item> <item name="android:minHeight">@dimen/abc_action_button_min_height_material</item> </style> <!--溢出菜单样式 --> <style name="over_flow_popList" parent="Base.Widget.AppCompat.ListPopupWindow"> <item name="overlapAnchor">true</item> <item name="android:dropDownSelector">?attr/listChoiceBackgroundIndicator</item> <item name="android:popupBackground">@drawable/abc_popup_background_mtrl_mult</item> <item name="android:dropDownVerticalOffset">0dip</item> <item name="android:dropDownHorizontalOffset">0dip</item> <item name="android:dropDownWidth">wrap_content</item> </style>
代码中设置溢出菜单:
@Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.home_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.github: return true; case R.id.me: return true; } return super.onOptionsItemSelected(item); }fragment:@Overridepublic void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.menu_sample, menu); super.onCreateOptionsMenu(menu,inflater);}
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"> <!-- ifRoom 表示 如果Toolbar 上有显示空间就显示在Toolbar 上,如果没有空间就展示在溢出菜单里 never 表是总是显示在溢出菜单里 always 表示总是显示在Toolbar 上 --> <item android:id="@+id/search" android:icon="@drawable/search" android:title="search" app:showAsAction="ifRoom" /> <item android:id="@+id/github" android:icon="@drawable/github" android:title="github" app:showAsAction="never" /> <item android:id="@+id/me" android:icon="@drawable/me" android:title="me" app:showAsAction="never" /></menu>
代码中设置属性:
// 设置 toolbar 背景色 toolbar.setBackgroundColor(getResources().getColor(R.color.colorPrimary)); // 设置 Title toolbar.setTitle(R.string.toolbar_title); // 设置Toolbar title文字颜色 toolbar.setTitleTextColor(getResources().getColor(R.color.white)); // 设置Toolbar subTitle toolbar.setSubtitle(R.string.sub_title); toolbar.setSubtitleTextColor(getResources().getColor(R.color.white)); // 设置logo toolbar.setLogo(R.mipmap.ic_launcher); // 设置 NavigationIcon 点击事件 toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); //设置 Toolbar menu toolbar.inflateMenu(R.menu.home_menu); // 设置溢出菜单的图标 toolbar.setOverflowIcon(getResources().getDrawable(R.drawable.toolbar));
CoordinatorLayout
CoordinatorLayout is a super-powered FrameLayout
用于协调子view,子view可以通过behavior 来做出相应的响应动作.CoordinatorLayout的使用核心就是Behavior
AppbarLayout
在使用CoordinatorLayout时,我们最常用的组合就是AppbarLayout,AppbarLayout 严重依赖于CoordinatorLayout,必须用于CoordinatorLayout 的直接子View。
当某个View滑动的时候,AppbarLayout 可以通过app:layout_scrollFlags来指定动作,以便让AppbarLayout 中的子view做出响应.
layout_scrollFlags有5种动作:
- scroll
- enterAlways
- enterAlwaysCollapsed
- exitUntilCollapsed
- snap
scroll
表示可滚动view滚动时,设置了该属性的view也会随之滚动 app:layout_scrollFlags="scroll"
enterAlways
拥有scroll的效果,并且可滚动view向下滑时,设置了该属性的view也会向下滑 app:layout_scrollFlags="scroll|enterAlways"
enterAlwaysCollapsed
下滑时,展开折叠(当可滚动view滑动到最顶部的时候) app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
exitUntilCollapsed
下滑时展开折叠,上滑到最顶部时,如果没有设置最小高度以及没有toolbar则会将整个内容向上移动 app:layout_scrollFlags="scroll|exitUntilCollapsed"
如果没有设置最小高度有toolBar则会以toolBar的高度为最小高度
snap
在滑动时手松开了,它自己会根据位置来回弹位置 app:layout_scrollFlags="scroll|snap"
注意: 你想使用这种动画必须先设置scroll属性,没有这个属性是触发滑动的
AppbarLayout 的几个重要方法
addOnOffsetChangedListener 当AppbarLayout里的子view偏移发生改变的时候回调。
getTotalScrollRange 返回AppbarLayout 所有子View的滑动范围
removeOnOffsetChangedListener 移除监听器
setExpanded (boolean expanded, boolean animate)设置AppbarLayout 是展开状态还是折叠状态,animate 参数控制切换到新的状态时是否需要动画
setExpanded (boolean expanded) 设置AppbarLayout 是展开状态还是折叠状态,默认有动画
CollapsingToolbarLayout
当我们想要在toolbar展开折叠时放入一下其他的view比如图片,那么就使用CollapsingToolbarLayout 来包装toolBar。
之前设置标题的时候都是设置toolBar的标题,现在则可以根据CollapsingToolbarLayout来设置
CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); collapsingToolbar.setTitle("Title");
当使用CollapsingToolbarLayout 的时候,status bar 应该设置半透明 (API 19)或者透明 (API 21)
<!-- res/values-v19/styles.xml --><style name="AppTheme" parent="Base.AppTheme"> <item name="android:windowTranslucentStatus">true</item></style><!-- res/values-v21/styles.xml --><style name="AppTheme" parent="Base.AppTheme"> <item name="android:windowDrawsSystemBarBackgrounds">true</item> <item name="android:statusBarColor">@android:color/transparent</item></style>
当你设置了透明属性,请保证你的跟布局设置android:fitsSystemWindow="true"
来达到好的视觉效果.
其他常用属性:
- contentScrim:app:contentScrim="@color/colorPrimary"
设置内容背景
- layout_collapseMode:app:layout_collapseMode="parallax"
视觉差效果
- layout_collapseMod:app:layout_collapseMode="pin"
固定子view
- Material Design for Android
- Android-Material-Design-for-pre-Lollipop
- Material Design for Developers
- WeijiaVisionApp For Material Design ,开源主流的Android Material Design UI 框架
- Android:AppCompat v21 - Material Design for Pre-Lollipop Devices!
- Android Material Design尝鲜
- Android Material Design
- Android Material Design Dialog
- Android:Material Design详解
- Android Material Design:PopupMenu
- Android Material Design:ListPopupWindow
- Android Material Design-UI
- Android Material Design动画
- Android Material Design:PopupMenu
- android Material design
- Android Material Design详解
- Android Material Design theme
- android Material Design详解
- Linux——给history命令加上用户和时间
- Mybatis的Executor介绍(一)
- 批量修改文件名
- 人人面经与不守诚信的人人公司
- hdu 2024 C语言合法标识符
- Material Design for Android
- java 传递可变参数
- 在ROS中添加多个机器人模型
- 前端基础进阶(十四):es6常用基础合集
- 用python提取caffemodel网络参数并保存为二进制文件.bat
- mysql的连接
- vuejs绑定数据到select中,选择option数据后,同步改变下面一个输入框input的值
- 传输层学习之一(传输层,UDP)
- Android蓝牙连接设备发送命令失效