Android 5.0 Material Design系列

Material Design(一) 简介

官网地址:https://developer.android.com/design/material/index.html

使用Material Design 需要api21,即Lollipop/5.0以上

Material Design 为应用提供了:一个新的主题,一些组合View的新Widget,一些自定义阴影和动画的新Api

Material 主题

   在manifest.xml 中<... android:theme="@android:style/Theme.Material" /> 提示一下有很多相关的主题


详见 使用Material主题


Lists和Cards

5.0提供了两个新的Widget,它们使用了Material Design 的style和animation:

    RecyclerView 一个更可插拔式的ListView,它支持不同的布局类型,并且性能有了改进。     列表式

    CardView 一个能让你在其内显示重要信息,并保持连贯的视觉和感觉的卡片  卡片式

    它两位于 sdk/extras/android/support/v7/cardview 和 sdk/extras/android/support/v7/RecyclerView


详见 创建列表和卡片


View的阴影

  View现在除了x、y属性外还有z,z代表一个view的仰角(elevation, 姑且这么翻译吧)

  z越大,阴影越大;z越大,view会出现在其他view的顶部

详见 定义阴影和裁剪View


动画

新的动画Api,让你在UI控件里能创建触摸反馈,改变View的状态,切换activity的一系列自定义动画

具体有:

响应View的touch事件的触摸反馈动画

隐藏和显示View的循环展示动画

两个Activity间的切换动画

更自然的曲线运动的动画

使用View的状态更改动画,能改变一个或多个View的属性

在View的状态更改时显示状态列表动画

   这些new animations Api,已内置在标准Widget中,如Button。在自定义view时也可使用这些api


详见 使用自定义动画


图片

可伸缩的矢量图片不会丢失清晰度,并且单一颜色的app-icon是完美的

可定义一个bitmap作为透明度(alpha)和运行时的颜色

可对一个bitmap image取色,会取出它比较显眼的颜色

详见 使用图片


附RecyclerView的例子:

[java]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. import android.app.Activity;  
  2. import android.os.Bundle;  
  3. import android.support.v7.widget.GridLayoutManager;  
  4. import android.support.v7.widget.RecyclerView;  
  5. import android.support.v7.widget.RecyclerView.LayoutParams;  
  6. import android.view.LayoutInflater;  
  7. import android.view.ViewGroup;  
  8. import android.widget.TextView;  
  9.   
  10. public class RecyclerViewActivity extends Activity {  
  11.     /* 
  12.      * recyclerview提供这些内置的布局管理器:  
  13.      * linearlayoutmanager              显示垂直滚动列表或水平的项目。 
  14.      * gridlayoutmanager                显示在一个网格项目。  
  15.      * staggeredgridlayoutmanager       显示在交错网格项目。 
  16.      * 自定义的布局管理器,需要继承recyclerview.layoutmanager类。 
  17.      *  
  18.      * add/remove items时的动画是默认启用的。 
  19.      * 自定义这些动画需要继承RecyclerView.ItemAnimator,并实现RecyclerView.setItemAnimator() 
  20.      */  
  21.      private RecyclerView mRecyclerView;  
  22.      private RecyclerView.Adapter mAdapter;  
  23.      private RecyclerView.LayoutManager mLayoutManager;  
  24.      private String[] myDataset;  
  25.   
  26.     @Override  
  27.     protected void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.           
  30.         setContentView(R.layout.recycler_view);  
  31.         mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);  
  32.   
  33.         // use this setting to improve performance if you know that changes  
  34.         // in content do not change the layout size of the RecyclerView  
  35.         mRecyclerView.setHasFixedSize(true);  
  36.   
  37.         // use a linear layout manager  
  38. //        mLayoutManager = new LinearLayoutManager(this);  
  39.           
  40. //        mLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, true);  
  41.         //true 表示,将layout内容反转  
  42.         mLayoutManager = new GridLayoutManager(this3, GridLayoutManager.VERTICAL, false);  
  43.         //HORIZONTAL 横向滚动显示内容   VERTICAL纵向  
  44. //        mLayoutManager = new GridLayoutManager(this, 3, GridLayoutManager.HORIZONTAL, false);  
  45.           
  46.         //方向也是指示滚动方向,例子中横向开头的数据交错了一点, 纵向的无交错  
  47. //        mLayoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL);  
  48. //        mLayoutManager = new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL);  
  49.           
  50.         mRecyclerView.setLayoutManager(mLayoutManager);  
  51. //        mRecyclerView.setLayoutManager(new MyLayoutMnager()); //数据不显示,可能还需要重写什么东西。。  
  52.   
  53.         // specify an adapter (see also next example)  
  54.         
  55.         setDatas();  
  56.         mAdapter = new MyAdapter(myDataset);  
  57.         mRecyclerView.setAdapter(mAdapter);  
  58.     }  
  59.       
  60.     private void setDatas() {  
  61.         int len = 200;  
  62.         myDataset = new String[len];  
  63.         for (int i = 0; i < len; i++) {  
  64.             switch (i%3) {  
  65.             case 0:  
  66.                 myDataset[i] = "中国" + i;  
  67.                 break;  
  68.             case 1:  
  69.                 myDataset[i] = "美国" + i;  
  70.                 break;  
  71.             case 2:  
  72.                 myDataset[i] = "澳大利亚" + i;  
  73.                 break;  
  74.             }  
  75.         }  
  76.     }  
  77.       
  78.     class MyLayoutMnager extends RecyclerView.LayoutManager {  
  79.   
  80.         @Override  
  81.         public LayoutParams generateDefaultLayoutParams() {  
  82.             LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
  83.             params.topMargin = 5;  
  84.             return params;  
  85.         }  
  86.     }  
  87.       
  88.     class MyAdapter extends RecyclerView.Adapter<ViewHolder> {  
  89.         private String[] mDataset;  
  90.   
  91.         // Provide a reference to the views for each data item  
  92.         // Complex data items may need more than one view per item, and  
  93.         // you provide access to all the views for a data item in a view holder  
  94.   
  95.         // Provide a suitable constructor (depends on the kind of dataset)  
  96.         public MyAdapter(String[] myDataset) {  
  97.             mDataset = myDataset;  
  98.         }  
  99.   
  100.         // Create new views (invoked by the layout manager)  
  101.         @Override  
  102.         public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
  103.             // create a new view  
  104.             TextView tv = (TextView) LayoutInflater.from(parent.getContext())  
  105.                     .inflate(R.layout.my_text_view, parent, false);  
  106.             // set the view's size, margins, paddings and layout parameters  
  107.             //...  
  108.             ViewHolder vh = new ViewHolder(tv); //构建一个ViewHolder  
  109.             return vh;  
  110.         }  
  111.   
  112.         // Replace the contents of a view (invoked by the layout manager)  
  113.         @Override  
  114.         public void onBindViewHolder(ViewHolder holder, int position) {  
  115.             // - get element from your dataset at this position  
  116.             // - replace the contents of the view with that element  
  117.             holder.mTextView.setText(mDataset[position]);  
  118.   
  119.         }  
  120.   
  121.         // Return the size of your dataset (invoked by the layout manager)  
  122.         @Override  
  123.         public int getItemCount() {  
  124.             return mDataset.length;  
  125.         }  
  126.     }  
  127.       
  128.     static class ViewHolder extends RecyclerView.ViewHolder {  
  129.         // each data item is just a string in this case  
  130.         public TextView mTextView;  
  131.         public ViewHolder(TextView v) {  
  132.             super(v);  
  133.             mTextView = v;  
  134.         }  
  135.     }  
  136. }  

Material Design(二) 入门指南

开始

1. 审查 材料设计规范
2. 应用材料设计主题
3. 以材料设计的指导方针来创建layouts
4. 投影:指定view的  evevation 属性 
5. 使用系统组件 lists and cards
6. 自定义动画

保持向后兼容性



Apply the Material Theme 运用材料主题

<!-- res/values/styles.xml -->
<resources>
  <!-- your theme inherits from the material theme -->
  <style name="AppTheme" parent="android:Theme.Material">
    <!-- theme customizations -->
  </style>
</resources>


Design Your Layouts  设计你的布局

除了应用和自定义材料的主题,你的布局应符合材料的设计准则。当你设计你的布局,以下需要特别注意:

· 基线网格

· Keylines

· 间距

· 触摸目标尺寸

· 布局结构


Specify Elevation in Your Views  在View中指定elevation属性

View可以投下的阴影,一个View的elevation值决定了它的阴影的大小和绘制的顺序。 可以设置一个视图的elevation ,在 布局中使用 属性 :android:elevation
<TextView
    android:id="@+id/my_textview"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/next"
    android:background="@color/white"
    android:elevation="5dp" />

新的translationz属性使您能够创建一个反映了暂时的elevation变化的动画。elevation的变化可在响应触摸手势时可能是有用的

 详见 定义阴影和裁剪View


创建 Lists and Cards

RecyclerView是一个可插入版本的列表视图,支持不同的布局类型并提供性能改进
CardView 允许您在app中显示一块块 使用一致外观的卡片
下面的代码示例演示了如何在你的布局: CardView
[html]  view plain  copy
 print ?
  1. <android.support.v7.widget.CardView  
  2.     android:id="@+id/card_view"  
  3.     android:layout_width="200dp"  
  4.     android:layout_height="200dp"  
  5.     card_view:cardCornerRadius="3dp">  
  6.     ...  
  7. </android.support.v7.widget.CardView>  

详见 创建 Lists and Cards


Customize Your Animations  自定义动画

可以自定义动画,如激活Activity的过渡动画和结束过渡动画
public class MyActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // enable transitions
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        setContentView(R.layout.activity_my);
    }

    public void onSomeButtonClicked(View view) {
        getWindow().setExitTransition(new Explode());
        Intent intent = new Intent(this, MyOtherActivity.class);
        startActivity(intent,
                      ActivityOptions
                          .makeSceneTransitionAnimation(this).toBundle());
    }
}
当你在这个Activity中启动其他的Activity时,exit transition将被激活

详见 使用自定义动画

Material Design(三) 使用Material主题

官网地址:https://developer.android.com/training/material/theme.html


新的Material主题提供了:

· 系统Widgets可设置它们的调色板

· 系统Widgets的触摸反馈动画

· Activity的过渡动画


您可以自定义Material主题,根据你的品牌标识,用一个调色板来控制。

可以使用主题属性来为操作栏和状态栏着色,如图所示:



Material主题的定义:
@android:style/Theme.Material (dark version)
@android:style/Theme.Material.Light (light version)
@android:style/Theme.Material.Light.DarkActionBar

注:Material主题只能5.0(api21)及以上才能使用support-v7提供了兼容支持。 详见保持兼容性

Customize the Color Palette  自定义调色板

自定义 基于颜色的 适合你的品牌的主题,当继承了Material主题时,可以使用Material主题中的属性来自定义颜色
<resources>
  <!-- inherit from the material theme -->
  <style name="AppTheme" parent="android:Theme.Material">
    <!-- Main theme colors -->
    <!--   your app branding color for the app bar -->
    <item name="android:colorPrimary">@color/primary</item>
    <!--   darker variant for the status bar and contextual app bars -->
    <item name="android:colorPrimaryDark">@color/primary_dark</item>
    <!--   theme UI controls like checkboxes and text fields -->
    <item name="android:colorAccent">@color/accent</item>
  </style>
</resources>

Customize the Status Bar  自定义状态栏

Material主题可以让你轻松地定制状态栏,所以您可以指定一个适合你品牌的颜色,并提供足够的对比度显示白色的状态图标,

当继承自Material主题时,设置状态栏时自定义颜色:android:statusBarColor。默认情况下,android:statusBarColor继承了android:colorPrimaryDark。

你可以自己绘制状态栏。例如,你想在照片上能明显的显示状态栏,用一个细微的黑色渐变来确保白色状态栏图标可见。为此,设置android:statusBarColor属性为@android:color/transparent,并根据需要调整Window的flags。对于动画或消退(fading),你也可以使用Window.setStatusBarColor()方法

当你自定义导航和状态栏时,要么使它们都透明,要么只修改状态栏。导航栏在其他所有情况下必须保持黑色。

Theme Individual Views  个人主题View

在layout的xml定义中,可以使用android:theme来指定该View所适用的主题,指定后,它将改变当前View及其子View的theme。

Material Design(四) 创建列表和卡片

官网:https://developer.android.com/training/material/lists-cards.html

在你的应用程序,创建复杂的列表和卡片与材料设计风格,您可以使用RecyclerView和CardView部件。


创建列表

RecyclerView组件是一个更先进和灵活的版本的列表视图。这个小部件是一个非常有效率的容器,通过有限的views,可以滚动显示大型数据集。
RecyclerView组件数据集合的元素,可在运行时根据用户操作或网络事件进行改变。

RecyclerView类简化了显示和处理大型数据集,它提供了:

· 布局管理器

· 常见的默认动画item操作,如删除、添加项目

你可以在RecyclerView中灵活定义 布局管理器和动画



要使用RecyclerView组件,您必须指定一个适配器和布局管理器。创建一个适配器,继承RecyclerView.Adapter类。有关更多信息,请参见下面的例子。

RecyclerView并确定重用项目视图时,布局管理器的利用item的方法,不再是对用户可见。重用(或回收)视图,布局管理器可能会问适配器,替换内容为不同的数据集的元素。回收view时,以这种方式来改进性能:避免创建不必要的view或执行消耗大的findViewById()查询。


RecyclerView提供了如下管理器:

· LinearLayoutManager  横向或纵向的滚动列表

· GridLayoutManager  网格列表

· StaggeredGridLayoutManager  交错的网格列表

要创建一个自定义布局管理器,需要继承RecyclerView.LayoutManager类


动画

添加和删除item的动画,在RecyclerView默认启用。定制这些动画,需要继承RecyclerView.ItemAnimator类并使用RecyclerView.setItemAnimator()方法。

例子

layout
[html]  view plain  copy
 print ?
  1. <!-- A RecyclerView with some commonly used attributes -->  
  2. <android.support.v7.widget.RecyclerView  
  3.     android:id="@+id/my_recycler_view"  
  4.     android:scrollbars="vertical"  
  5.     android:layout_width="match_parent"  
  6.     android:layout_height="match_parent"/>  

activity
[html]  view plain  copy
 print ?
  1. public class MyActivity extends Activity {  
  2.     private RecyclerView mRecyclerView;  
  3.     private RecyclerView.Adapter mAdapter;  
  4.     private RecyclerView.LayoutManager mLayoutManager;  
  5.   
  6.     @Override  
  7.     protected void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.my_activity);  
  10.         mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);  
  11.   
  12.         // use this setting to improve performance if you know that changes  
  13.         // in content do not change the layout size of the RecyclerView  
  14.         mRecyclerView.setHasFixedSize(true); //使用固定size 以优化性能  
  15.   
  16.         // use a linear layout manager  
  17.         mLayoutManager = new LinearLayoutManager(this);  
  18.         mRecyclerView.setLayoutManager(mLayoutManager);  
  19.   
  20.         // specify an adapter (see also next example)  
  21.         mAdapter = new MyAdapter(myDataset);  
  22.         mRecyclerView.setAdapter(mAdapter);  
  23.     }  
  24.     ...  
  25. }  

adapter
[java]  view plain  copy
 print ?
  1. public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {  
  2.     private String[] mDataset;  
  3.   
  4.     // Provide a reference to the views for each data item  
  5.     // Complex data items may need more than one view per item, and  
  6.     // you provide access to all the views for a data item in a view holder  
  7.     public static class ViewHolder extends RecyclerView.ViewHolder {  
  8.         // each data item is just a string in this case  
  9.         public TextView mTextView;  
  10.         public ViewHolder(TextView v) {  
  11.             super(v);  
  12.             mTextView = v;  
  13.         }  
  14.     }  
  15.   
  16.     // Provide a suitable constructor (depends on the kind of dataset)  
  17.     public MyAdapter(String[] myDataset) {  
  18.         mDataset = myDataset;  
  19.     }  
  20.   
  21.     // Create new views (invoked by the layout manager)  
  22.     @Override  
  23.     public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,  
  24.                                                    int viewType) {  
  25.         // create a new view  
  26.         TextView v = (TextView)LayoutInflater.from(parent.getContext())  
  27.                                .inflate(R.layout.my_text_view, parent, false);  
  28.         // set the view's size, margins, paddings and layout parameters  
  29.         ...  
  30.         ViewHolder vh = new ViewHolder(v);  
  31.         return vh;  
  32.     }  
  33.   
  34.     // Replace the contents of a view (invoked by the layout manager)  
  35.     @Override  
  36.     public void onBindViewHolder(ViewHolder holder, int position) {  
  37.         // - get element from your dataset at this position  
  38.         // - replace the contents of the view with that element  
  39.         holder.mTextView.setText(mDataset[position]);  
  40.   
  41.     }  
  42.   
  43.     // Return the size of your dataset (invoked by the layout manager)  
  44.     @Override  
  45.     public int getItemCount() {  
  46.         return mDataset.length;  
  47.     }  
  48. }  

创建卡片

CardView继承自FrameLayout,以卡片式显示一致的外观。它可以有阴影和圆角
创建一个有阴影的卡片,使用card_view:cardElevation属性。

使用这些属性来定制CardView组件的外观:
· 在你的布局设置圆角半径,使用card_view:cardCornerRadius属性
· 在代码中设置圆角半径,使用CardView.setRadius方法
· 设置卡片的背景颜色,使用card_view:cardBackgroundColor属性
[java]  view plain  copy
 print ?
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     xmlns:card_view="http://schemas.android.com/apk/res-auto"  
  4.     ... >  
  5.     <!-- A CardView that contains a TextView -->  
  6.     <android.support.v7.widget.CardView  
  7.         xmlns:card_view="http://schemas.android.com/apk/res-auto"  
  8.         android:id="@+id/card_view"  
  9.         android:layout_gravity="center"  
  10.         android:layout_width="200dp"  
  11.         android:layout_height="200dp"  
  12.         card_view:cardCornerRadius="4dp">  
  13.   
  14.         <TextView  
  15.             android:id="@+id/info_text"  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="match_parent" />  
  18.     </android.support.v7.widget.CardView>  
  19. </LinearLayout>  

添加依赖

gradle依赖
[plain]  view plain  copy
 print ?
  1. dependencies {  
  2.     ...  
  3.     compile 'com.android.support:cardview-v7:21.0.+'  
  4.     compile 'com.android.support:recyclerview-v7:21.0.+'  
  5. }  

Material Design(五) 定义阴影和裁剪View

官网:https://developer.android.com/training/material/shadows-clipping.html


材料设计介绍了UI元素的evevation属性,帮助用户了解每个元素相对重要性

每个View的elevation值,相当于z属性,它决定了阴影的大小:z越大,阴影越大。

Views仅仅在z=0的平面上才会投影;它们不会投影在放置在它们下面和上面的的其他Views上。

使用较高z值的Views会阻隔使用较低z值的Views。

然而,一个View的Z值不会影响View的大小。

elevation有利于创建 在组件需要临时上升到View的平面之上做一些操作时 的动画。

更多关于elevation的介绍,详见http://www.google.com/design/spec/what-is-material/elevation-shadows.html


Assign Elevation to Your Views  在Views中指定Elevation

Z值包含两个成分:elevation和translation。 elevation是一个静态的成分,translation使用了动画:Z = elevation + translationZ


在layout中设置elevation,使用android:elevation属性。在代码中设置,使用View.setElevation()方法。

设置一个View的translation,使用View.setTranslationZ()方法。

ViewPropertyAnimator.z()和ViewPropertyAnimator.translationZ() 能使你更轻易的推动Views的elevation。

您还可以使用一个StateListAnimator指定这些动画声明的方式。在状态改变触发动画的情况下,这是特别有用的,比如当用户按下一个按钮时。

Customize View Shadows and Outlines  自定义View的阴影和轮廓

View的背影图片的边界确定了阴影的默认图形。轮廓代表一个图形对象的外部形状和定义的用于触摸反馈的波纹区域。
参考:
<TextView
    android:id="@+id/myview"
    ...
    android:elevation="2dp"
    android:background="@drawable/myrect" />
背景图片可以定义成一个圆角的矩形
<!-- res/drawable/myrect.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
    <solid android:color="#42000000" />
    <corners android:radius="5dp" />
</shape>
因为背景图片定义了View的轮廓(outline),所以View会投放一个使用了圆角的阴影。提供一个自定义的轮廓重写View的默认阴影图形。
自定义轮廓在代码中:
·继承自ViewOutlineProvider
·重写getOutline()
·使用View.setOutlineProvider(),指派新的轮廓

使用Outline类的一些方法,创建圆角矩形和 椭圆的轮廓。默认的outline provider 包含了View的背影轮廓。阻止一个View的投影,可以设置View的ouline provider 为null。

Clip Views  裁剪


剪裁视图使您能够轻松地更改视图的形状。你可以统一裁剪成使用了其他设计元素,或在响应用户输入时改变View的形状。可以裁剪View的外部轮廓区域,使用View.setClipToOutline()或者android:clipToOutline属性。只有矩形、圆形、圆角矩形支持轮廓的裁剪,由Outline.canClip()方法来确定。
当要裁剪成一个图片的形状时,需要设置该图片为View的背景,并调用 View.setClipToOutline()。
裁剪是一个奢侈的操作,不要使用动态图形来裁剪。为了实现这种效果,可以使用动画来展现。

Material Design(六) 使用图片

官网地址:https://developer.android.com/training/material/drawables.html


以下图片的功能能帮助你在app中实现Material设计:

·图片着色

·颜色提取

·矢量图片

Tint Drawable Resources  为图片资源染色

在Android 5.0(API级别21)及以上,你可以将图片和9-patch定义为掩饰透明度。你能使用颜色资源(如,?android:attr/colorPrimary)或主题属性来给它们上色。通常,你只需创建这些资源一次,且自动匹配你的主题为它们上色。

可以为BitmapDrawable和NinePatchDrawable 的对象使用setTint(int tint)进行染色。也可以在xml中定义android:tint和android:tintMode属性。

·关于setTint(int tint)的参数,可以是一个@color/下的属性,也可以是一个xml的selector,selector中的item是使用了数字的,如:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
   <item android:state_focused="true" android:color="@color/testcolor1"/>
   <item android:state_pressed="true" android:state_enabled="false" android:color="@color/testcolor2" />
   <item android:state_enabled="false" android:color="@color/testcolor3" />
   <item android:color="@color/testcolor5"/>
 </selector>

·关于xml中定义属性,如:
<?xmlversion="1.0"encoding="utf-8"?>
<nine-patchxmlns:android="http://schemas.android.com/apk/res/android" 
    android:tint="@color/abc_primary_text_material_light" 
    android:tintMode="src_over"
    ... >
</nine-patch>

Extract Prominent Colors from an Image  从图片抽取明显的颜色

在api21上的support-v7库中有一个android-support-v7-palette.jar,它能够让你从图片中抽取一些显眼的颜色:

Palette p = Palette.generate(Bitmap bitmap);

·鲜艳的                p.getVibrantColor(int defaultColor);
·鲜艳的黑暗         p.getDarkVibrantColor(int defaultColor);
·鲜艳的明亮         p.getLightVibrantColor(int defaultColor);
·柔和的                p.getMutedColor(int defaultColor);
·柔和的黑暗         p.getDarkMutedColor(int defaultColor);
·柔和的明亮         p.getLightMutedColor(int defaultColor);
Palette.generate(),用于在后台线程中执行,如果在前台线程中创建Palette对象,那么可以使用Palette.generateAsync()。

Create Vector Drawables  创建矢量图片

在Android 5.0(API级别21)及以上 可以创建矢量图片,如下面的例子可以绘制一个心形的矢量图:
<!-- res/drawable/heart.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    <!-- intrinsic size of the drawable -->
    android:height="256dp"
    android:width="256dp"
    <!-- size of the virtual canvas -->
    android:viewportWidth="32"
    android:viewportHeight="32">

  <!-- draw a path -->
  <path android:fillColor="#8fff"
      android:pathData="M20.5,9.5
                        c-1.955,0,-3.83,1.268,-4.5,3
                        c-0.67,-1.732,-2.547,-3,-4.5,-3
                        C8.957,9.5,7,11.432,7,14
                        c0,3.53,3.793,6.257,9,11.5
                        c5.207,-5.242,9,-7.97,9,-11.5
                        C25,11.432,23.043,9.5,20.5,9.5z" />
</vector>
矢量图片在Android中使用VectorDrawble对象与之对应。path的更多信息请见:http://www.w3.org/TR/SVG11/paths.html#PathData。

Material Design(七) 自定义动画

官网地址:https://developer.android.com/training/material/animations.html


动画在Material设计中,为用户与app交互反馈他们的动作行为和提供了视觉上的连贯性。Material主题为Buttons和Activity的过渡提供了一些默认的动画,在android5.0(api21)及以上,允许自定义这些动画:

· Touch feedback  触摸反馈

· Circular Reveal  循环显示

· Activity transitions  活动过渡

· Curved motion       曲线运动

· View state changes  视图状态变化

Customize Touch Feedback  自定义触摸反馈动画

在Material设计中,触摸反馈提供了一种在用户与UI进行交互时 即时可视化的确认接触点。关于buttons默认的触摸反馈动画,使用了RippleDrawable类,用一个波纹(涟漪)效果在两种不同的状态间过渡。

在多数情况下,你需要在view的xml定义中,定义它的背景:

?android:attr/selectableItemBackground                              有界限的波纹    

?android:attr/selectableItemBackgroundBorderless             延伸到view之外的波纹     note:该属性为api21添加

或者,你可以用xml定义一个RippleDrawable类型的资源,并使用波纹属性。

你可以指定一个颜色给RippleDrawable对象,以改变它的默认触摸反馈颜色,使用主题的android:colorControlHighlight属性。

Use the Reveal Effect  使用展现效果

ViewAnimationUtils.createCircularReveal()方法使您能够激活一个循环显示或隐藏一个视图。

显示:

// previously invisible view
View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the final radius for the clipping circle
int finalRadius = myView.getWidth();

// create and start the animator for this view
// (the start radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
anim.start();

隐藏

// previously visible view
final View myView = findViewById(R.id.my_view);

// get the center for the clipping circle
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;

// get the initial radius for the clipping circle
int initialRadius = myView.getWidth();

// create the animation (the final radius is zero)
Animator anim =
    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);

// make the view invisible when the animation is done
anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        myView.setVisibility(View.INVISIBLE);
    }
});

// start the animation
anim.start();

Customize Activity Transitions  定义Activity的过渡动画

·一个enter transition表示,Activity的进入场景。比如一个explode enter transition,表示Views的进入场景:飞快的从外部向屏幕中心移动。

·一个exit transition表示,Activity的离开场景。比如一个explode exit transition,表示Views的离开场景:从屏幕中心散开。

·一个share transition表示,在两个Activity间共享它们的activity transtion。比如,两个Activity有一个相同的图片,而位置和尺寸不同,使用changeImageTransform这个共享元素,能在Activity间平稳的转换和缩放图片。


android5.0(api21)及以上,支持这些效果的transition(过渡):

爆炸——移动视图或从场景中心。class Explode

滑行——移动视图或从一个场景的边缘。class Slide

淡入淡出——添加或从场景中删除视图通过改变其透明度。 class Fade

也支持这些共享元素(都有对应的class)转换:
  changeBounds ——View的布局的边界变化。
  changeClipBounds——View的裁剪边界变化。
  changeTransform——View的旋转、缩放边界变化
  changeImageTransform——目标图像的尺寸和缩放变化。
  当启用活动在你的应用程序转换,默认同时淡出淡入之间的过渡是激活进入和退出活动。

Specify custom transitions 自定义过渡动画

首先需要在定义主题的style中,使用android:windowContentTransitions属性,声明使用transitions。也可以定义使用的Transitions:

[html]  view plain  copy
 print ? 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <style name="MyTheme" parent="@android:style/Theme.Material">  
  4.         <!-- enable window content transitions -->  
  5.         <item name="android:windowContentTransitions">true</item>  
  6.         <!-- specify enter and exit transitions -->  
  7.         <item name="android:windowEnterTransition">@android:transition/explode</item>  
  8.         <item name="android:windowExitTransition">@android:transition/explode</item>  
  9.         <!-- specify shared element transitions -->  
  10.         <item name="android:windowSharedElementEnterTransition">@android:transition/move</item>  
  11.         <item name="android:windowSharedElementExitTransition">@android:transition/slide_top</item>  
  12.     </style>  
  13. </resources>  


注:每个transition的xml中定义的就是一组change的元素

在代码中启用transitions:

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an exit transition
getWindow().setExitTransition(new Explode());

在代码中设置transitions的方法还有

要想尽快进行transitions过渡,可在Activity中调用Window.setAllowEnterTransitionOverlap()

Start an activity using transitions 使用过渡启动Activity

如果你要启用transtions并设置为一个Activity的结束exit transtion,当你以如下方式启动另一个Activity时,它将被激活:
startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this).toBundle());
当你在另一个Activity中设置了enter transtion,在其启动时,它将被激活。想要disable transitions,那么在启动另一个Activity时:

startActivity(intent,null);  //传递null 的options bundle

Start an activity with a shared element  使用一个共享元素启动Acitvity


1.在主题中启用window content 

2.在style中定义共享的过渡transitions

3.定义transitions的xml资源  res/transition

4.在layout中调用android:transitionName="" 设置第3步中定义的名字

5.调用 ActivityOptions.makeSceneTransitionAnimation()生成相应的ActivityOptions对象。

// get the element that receives the click event
final View imgContainerView = findViewById(R.id.img_container);

// get the common element for the transition in this activity
final View androidRobotView = findViewById(R.id.image_small);

// define a click listener
imgContainerView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent = new Intent(this, Activity2.class);
        // create the transition animation - the images in the layouts
        // of both activities are defined with android:transitionName="robot"
        ActivityOptions options = ActivityOptions
            .makeSceneTransitionAnimation(this, androidRobotView, "robot");
        // start the new activity
        startActivity(intent, options.toBundle());
    }
});

在代码中可以用View.setTransitionName()来设置过渡动画

当你要关闭第二个Activity时,要反转过渡动画,那么可以调用Activity.finishAfterTransition()方法,而不是Activity.finish()。

Start an activity with multiple shared elements  用多共享元素启动Activity

若两个Activity拥有不只一个的共享元素,要在它们之间开始场景transition动画,在它们的layout中都要使用 android:transitionName (或在Activity中代码中调用View.setTransitionName() )来定义,并创建一个如下的 ActivityOptions 对象:

ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(view1, "agreedName1"),
        Pair.create(view2, "agreedName2"));

Use Curved Motion 使用曲线运动

在Material设计中的动画,依赖于曲线的时间插入值和空间运动模式。在android5.0(api21)及以上,可以自定义动画时间曲线和曲线运动模式。

PathInterpolator类是一个新的基于贝塞尔曲线或路径对象的插入器。这个插入器指定了一个1 x1正方形运动曲线,它使用(0,0)为锚点,(1,1)为控制点,作为构造函数的参数。你也可以定义一个path interpolator的xml资源:

<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
    android:controlX1="0.4"
    android:controlY1="0"
    android:controlX2="1"
    android:controlY2="1"/>

系统提供了三种基本的曲线,XML资源:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

您可以用PathInterpolator对象作Animator.setInterpolator()方法的参数。

ObjectAnimator类有新构造函数使您能够激活坐标沿着一个path同时使用两种或两种以上的属性。比如,如下的animator就使用了一个path 对象,来同时操作View的x和y属性:

ObjectAnimator mAnimator;
mAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
...
mAnimator.start();

Animate View State Changes  视图状态改变动画


StateListAnimator类允许您定义动画运行时视图的状态变化。下面的例子演示如何在xml中定义一个StateListAnimator:

<!-- animate the translationZ property of a view when pressed -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="@android:integer/config_shortAnimTime"
        android:valueTo="2dp"
        android:valueType="floatType"/>
        <!-- you could have other objectAnimator elements
             here for "x" and "y", or other properties -->
    </set>
  </item>
  <item android:state_enabled="true"
    android:state_pressed="false"
    android:state_focused="true">
    <set>
      <objectAnimator android:propertyName="translationZ"
        android:duration="100"
        android:valueTo="0"
        android:valueType="floatType"/>
    </set>
  </item>
</selector>

在上例中,为一个View添加视图状态动画,定义了一个使用selector元素的xml资源,并赋给view的android:stateListAnimator属性。如要在代码中为View指定视图状态动画,可使用AnimationInflater.loadStateListAnimator()加载xml资源,并使用View.setStateListAnimator()将其指定给View。

当你的主题继承了Material主题,按钮默认拥有了z动画。为了避免这种行为在你的按钮,设置android:stateListAnimator属性值为null。

AnimatedStateListDrawable类允许您创建图片以显示关联View的状态改变动画。一些系统的Widget,在5.0上默认使用这些动画。下面的例子显示了如何定义一个AnimatedStateListDrawable作为XML资源:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

Animate Vector Drawables  矢量图片动画

矢量图片是可伸缩而不失真的。AnimatedVectorDrawable类让你能使一个矢量图动起来。

通常在三种xml定义动态的矢量图:

·使用<vector>元素的矢量图,在res/drawable/

·一个动态矢量图,使用<animated-vector>元素,在res/drawable/

·一个或多个object animator,使用<objectAnimator>元素,在res/animator/

矢量图可以定义的属性元素有<group>和<path>,<group>定义了一个<path>的集合,或者子<group>,<path>定义绘制的路径。

定义矢量图时,可以给<group>和<path>指定一个名字,示例如下:

<!-- res/drawable/vectordrawable.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="64dp"
    android:width="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600">
    <group
        android:name="rotationGroup"
        android:pivotX="300.0"
        android:pivotY="300.0"
        android:rotation="45.0" >
        <path
            android:name="v"
            android:fillColor="#000000"
            android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />
    </group>
</vector>

在矢量动画中,引用矢量图定义的名字:
<!-- res/drawable/animvectordrawable.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
  android:drawable="@drawable/vectordrawable" >
    <target
        android:name="rotationGroup"
        android:animation="@anim/rotation" />
    <target
        android:name="v"
        android:animation="@anim/path_morph" />
</animated-vector>
以下例子代表了一个   ObjectAnimator  or  AnimatorSet  对象:动作为旋转360度
<!-- res/anim/rotation.xml -->
<objectAnimator
    android:duration="6000"
    android:propertyName="rotation"
    android:valueFrom="0"
    android:valueTo="360" />

下面的例子表示矢量图path从一个图形到另一个。两种渐变路径必须一致:他们必须具有相同数量的命令和相同数量的每个命令的参数:

<!-- res/anim/path_morph.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="3000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0   -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0  0,140 -70,0 z"
        android:valueType="pathType" />
</set>

更多详见:AnimatedVectorDrawable .

Material Design(八) 保持兼容性

Define Alternative Styles  定义替代样式

让你的app,使用Material Design的主题运行在支持它的设备上,并在早期版本的设备上可以运行较早的主题:
1. 在res/values/styles.xml 定义一个主题继承较早的主题
2. 在res/values-v21/styles.xml 定义一个相同名字的继承自Material主题 的主题 
3. 在manifest中应用定义的主题
注:如果你的app使用了Material 主题,而不提供较早的主题,那么将不能运行在早期版本的设备上

Provide Alternative Layouts  提供替代布局

如果你设计的layout不引用任何的5.0中的xml属性,那么可以运行在早期版本的Android设备上。否则,你可提供一个替代布局。
替代布局建立在res/layout-v21/
为了避免重复代码,可以在res/values/  定义你的styles,新风格的在res/values-21/ 中定义,并使用style的继承,在res/values中定义一个baseStyle,在res/values-21中继承它。

Use the Support Library  使用支持库

v7 support library 包括以下的一些特性:
· 在应用了一个Theme.AppCompat 主题后,系统的一些组件就有了Material Design 的风格
· 在Theme.AppCompat 主题中,有调色主题
· RecyclerView 组件显示数据集
· CardView 组件创建卡片
· 从图像中取色

System widgets  系统组件

Theme.AppCompat 主题提供的Material Design 风格的组件有:
· EditText
· Spinner
· CheckBox
· Radiobutton
· SwitchCompat
· CheckedTextView

Color Palette

使用v7支持库,获得Material Design 风格定义颜色板,应用一个Theme.AppCompat 主题:
<!-- extend one of the Theme.AppCompat themes -->
<style name="Theme.MyTheme" parent="Theme.AppCompat.Light">
    <!-- customize the color palette -->
    <item name="colorPrimary">@color/material_blue_500</item>
    <item name="colorPrimaryDark">@color/material_blue_700</item>
    <item name="colorAccent">@color/material_green_A200</item>
</style>

Lists and Cards

使用v7支持库后,在早期的Android版本上也可运行。

Dependencies

gradle 依赖:
dependencies {
    compile 'com.android.support:appcompat-v7:21.0.+'
    compile 'com.android.support:cardview-v7:21.0.+'
    compile 'com.android.support:recyclerview-v7:21.0.+'
}

Check the System Version  检查系统版本


以下特性只能在Android 5.0(API级别21)及以上:
· Activity transitions  活动转换
· Touch feedback    触觉反馈
· Reveal animations  显示动画
· Path-based animations  基于路径动画
· Vector drawables  矢量图片

· Drawable tinting  图片染色

检查代码:

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Call some material design APIs here
} else {
    // Implement this feature without material design
}

注:要让app支持5.0,需要在manifest中Android:targetSdkVersion=21。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值