Android Material Design I-基础知识

来源:互联网 发布:python 短文本相似度 编辑:程序博客网 时间:2024/04/28 08:53

概述:

是Android 5.0中引入的设计理念, 其核心理念是使设计更加接近现实, 通过控件的光影特效, 表面质感以及运动模式来模拟现实中的环境, 让用户在使用的时候可以产生自然而然的感觉, 降低学习成本. 并通过通话来聚焦用户注意力, 凸显重要的内容.

Material Design的环境包括3D世界和光影效果, 也就是模拟现实的主要手段.

3D世界以为Material的环境中包含三个维度, 分别用x,y,z轴表示. Z轴与显示面板垂直对齐. 每个material的sheet(一个薄片)在Z轴占据一个独立的位置并拥有1dp的厚度, 模拟图如下:


在material环境中, 会有虚拟的光线照亮所在的场景. 主要光源投射出一个定向的阴影, 而环境光源则从各个角度投射出柔和的阴影. Material中的阴影是由这两种光线产生的, 阴影的产生跟自然环境一样, 是由于sheet遮住了光线导致的.


上图是主要光源投射造成的阴影.


上图是由散射光源投射造成的阴影.


上图是主要光源和散射光源联合造成的阴影.

由此可知, Material Design中的变化均是由sheet在场景中的空间变化以及其导致的因应变化组合而来, 关于其变化原则可以参考Materialproperties和Elevationand shadows. 更夸张的是设计中还包含了重力和质量, 由于”重力”的关系, 在设计动画的时候速度应该是渐变的. 总之, 这里所作的一切都是为了让设计可以更遵循自然规则, 让用户使用更加容易上手. Material Design意在提供一种统一的设计交互的模式, 而不只是某些控件和用法.

不同版本可以使用的MaterialDesign功能:

Material Design是Android 5.0中引入的功能, 有些功能我们可以通过支持库在早起版本中使用, 也有些功能是必须在Android 5.0以上才能使用的.

支持库可以支持:

V7 Support Library r21及更高版本的支持库提供了以下功能的支持:

当使用Theme.AppCompat主题的时候可以使用Material design的样式.

l  在Theme.lightAppCompat主题中可以使用调色板主题属性.

l  可以使用RecyclerView来显示数据集合.

l  可以使用CardView来创建card.

l  可以使用Palette类来从图片中提取颜色.

其中Theme.AppCompat为这些控件提供了Material design样式, 包括EditText, Spinner, CheckBox, RadioButton, SwitchCompat,CheckedTextView.

要在Android 5.0之前的版本使用这些功能, 需要添加Android v7支持库:

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.+'
}

Android 5.0才可以支持的功能:

l  Activity变换(Activity transitions)

l  触摸反馈(Touchfeedback)

l  显示动画(Revealanimations)

l  基于路径的动画(Path-basedanimations)

l  矢量Drawable(Vectordrawables)

l  Drawable着色(Drawable tinting)

如果要使用这些功能, 需要在运行时对系统的版本进行判断:

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

创建一个使用Material Design的APP:

1.      复习materialdesign specification.

2.      为app设置Material theme.

3.      创建符合Material design原则的layout.

4.      指定view的高度来投射阴影.

5.      为list和card使用系统Widget.

6.      自定义app中的动画.

首先是使用Material Theme:

新的Material Theme提供了:

l  可以设置调色板的系统控件.

l  系统控件的触摸反馈动画.

l  Activity变化动画.

我们可以通过调色板来自定义Material design的外观. 还可以为action bar和状态栏着色. 系统组件有了新的设计和触摸反馈动画. 这些也是可以自定义的. Material design的主题可以这样定义:

l  @android:style/Theme.Material (dark version)

l  @android:style/Theme.Material.Light (light version)

l  @android:style/Theme.Material.Light.DarkActionBar


上图分别为暗色和亮色的Material主题. Material主题只能在Android 5.0及以上版本中使用, v7支持库提供的主题可以支持一部分的控件的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>

自定义状态栏:

Material主题让我们可以很容易的自定义状态栏, 这样就可以为状态栏指定颜色以符合我们的app的色调了. 要为状态栏设置一个自定义的颜色, 当我们使用material主题时需要使用android:statusBarColor属性. 默认情况下, android:statusBarColor继承了android:colorPrimaryDark的值.

我们还可以指定状态栏后面的图像. 比如可以在一张图片上使用一个透明的状态栏. 要这样做, 可以设置android:statusBarColor属性为@android:color/transparent并调整所需的窗口flag. 还可以使用Window.setStatusBarColor()方法来设置动画或者褪色.


提醒: 状态栏应该几乎总是跟Toolbar之间保持有一条清晰的界限, 除非有意的展示丰富的图像或者播放媒体.

当自定义导航和状态栏的时候, 要么它俩都是透明的, 要么就只修改状态栏. 在其它任何情况下导航栏应该保持黑色.

为单个View指定主题:

在layout的元素中可以指定andorid:theme属性, 它关联一个主题资源. 该属性修改所在标签及其子标签的主题, 可以用于修改指定UI的主题调色板.

创建List及Card:

可以使用RecyclerView和CardView组件来在Material Design中实现复杂的list和card.

创建List:

RecyclerView是一种更高级和灵活的ListView. 它可以用来显示大量的数据集合, 并通过限制view的数量使得它的滚动十分流畅. 当我们拥有的数据集合需要在运行时根据哟农户的操作或者网络事件修改的情况下, 可以使用RecyclerView. RecyclerView类通过这些简化了显示和处理大数据集合:

l  Layout manager用于定位item.

l  常用item操作的默认动画, 比如移除或者添加item.

还可以很灵活地定义layout manager和动画.


要使用RecyclerView, 必须制定一个adapter和一个layout manager. 创建adapter需要继承RecyclerView.Adapter类. Adapter的实现跟ListView类似, 需要根据app逻辑来实现.

Layout manager负责在RecyclerView中定位item view并决定什么时候重用不再对用户可见的item. 在这种工作模式中, 回收view可以通过避免创建不必要的view或者处理昂贵的findViewById()来提高性能.


RecyclerView提供了这些内置的layoutmanager:

LinearLayoutManager: 它在一个水平或者垂直的滚动list中显示item.

GridLayoutManager: 在一个表格中显示item.

StaggeredGridLayoutManager: 在一个交错网格中显示item.

要创建一个自定义的layout manager, 继承RecyclerView.LayoutManager类.

动画:

在RecyclerView中默认情况下就拥有添加和删除item的动画. 要自定义这些动画, 需要继承RecyclerView.ItemAnimator类并使用RecyclerView.setItemAnimator()方法.

栗子:

下面的代码演示了如何添加RecyclerView到一个layout:

<!-- A RecyclerView with some commonly used attributes --><android.support.v7.widget.RecyclerView    android:id="@+id/my_recycler_view"    android:scrollbars="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"/>

一旦添加了一个RecyclerView, 就可以在代码中获取它的对象并连接到一个layout manager, 然后关联一个adapter来指定要显示的数据:

public class MyActivity extends Activity {    private RecyclerView mRecyclerView;    private RecyclerView.Adapter mAdapter;    private RecyclerView.LayoutManager mLayoutManager;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.my_activity);        mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);        // use this setting to improve performance if you know that changes        // in content do not change the layout size of the RecyclerView        mRecyclerView.setHasFixedSize(true);        // use a linear layout manager        mLayoutManager = new LinearLayoutManager(this);        mRecyclerView.setLayoutManager(mLayoutManager);        // specify an adapter (see also next example)        mAdapter = new MyAdapter(myDataset);        mRecyclerView.setAdapter(mAdapter);    }    ...}

Adapter提供了对数据集合中的item的访问, 并为item创建view以及替代那些不再显示的view.下面的代码演示了一个简单的实现:

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {    private String[] mDataset;    // Provide a reference to the views for each data item    // Complex data items may need more than one view per item, and    // you provide access to all the views for a data item in a view holder    public static class ViewHolder extends RecyclerView.ViewHolder {        // each data item is just a string in this case        public TextView mTextView;        public ViewHolder(TextView v) {            super(v);            mTextView = v;        }    }    // Provide a suitable constructor (depends on the kind of dataset)    public MyAdapter(String[] myDataset) {        mDataset = myDataset;    }    // Create new views (invoked by the layout manager)    @Override    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,                                                   int viewType) {        // create a new view        View v = LayoutInflater.from(parent.getContext())                               .inflate(R.layout.my_text_view, parent, false);        // set the view's size, margins, paddings and layout parameters        ...        ViewHolder vh = new ViewHolder(v);        return vh;    }    // Replace the contents of a view (invoked by the layout manager)    @Override    public void onBindViewHolder(ViewHolder holder, int position) {        // - get element from your dataset at this position        // - replace the contents of the view with that element        holder.mTextView.setText(mDataset[position]);    }    // Return the size of your dataset (invoked by the layout manager)    @Override    public int getItemCount() {        return mDataset.length;    }}

创建Card:

CardView继承自FrameLayout类, 它可以在card中显示信息并为不同版本的平台提供一致的外观体验. CardView可以拥有阴影和圆角.


要创建一个带有阴影效果的card, 使用card_view:cardElevation属性. 在Android 5.0及更高版本中, CardView使用真实的高度和动态阴影.在更早的版本中则使用旧版本的阴影效果. 使用这些属性来自定义CardView的显示效果:

l  要在layout中设置圆角半径, 使用card_view:cardCornerRadius属性.

l  要在代码中设置圆角半径, 使用CardView.setRadius方法.

l  要设置card的背景色, 使用card_view:cardBackgroundColor属性.

下面的代码演示了如何在layout中包含一个CardView:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    xmlns:card_view="http://schemas.android.com/apk/res-auto"    ... >    <!-- A CardView that contains a TextView -->    <android.support.v7.widget.CardView        xmlns:card_view="http://schemas.android.com/apk/res-auto"        android:id="@+id/card_view"        android:layout_gravity="center"        android:layout_width="200dp"        android:layout_height="200dp"        card_view:cardCornerRadius="4dp">        <TextView            android:id="@+id/info_text"            android:layout_width="match_parent"            android:layout_height="match_parent" />    </android.support.v7.widget.CardView></LinearLayout>

依赖包:

RecyclerView和CardView是v7支持包的一部分. 要在工程中使用它们, 需要添加依赖:

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

定义阴影和clipping view:

Material design为UI引入了”高度(Elevation)”的概念. 它可以帮助用户理解每个元素的相对重要性并将注意力集中在当前的任务上.

View的高度代表Z轴的坐标(也就是通过Z轴来表示高度). 它决定了view的阴影: 更高的view拥有更大更柔和的阴影. 更高的view可以覆盖较低的view. 但是高度不会影响view的尺寸.  View的阴影由它的parent负责绘制, 因此符合标准view裁剪, 默认由parent裁剪.

为view分配高度值:

View的z值包括两个部分:

高度: 静态部分.

变化(Translation): 用于动画的动态部分.

Z = 高度 + TranslationZ


不同高度下view的阴影效果.

要在layout中设置view的高度, 使用android:elevation属性. 如果在代码中设置, 则使用View.setElevation()方法. 要设置view的变化高度, 使用View.setTranslationZ()方法.

新的ViewPropertyAnimator.z()和ViewPropertyAnimator.translationZ()方法使得修改view的高度变得更加容易. 更多关于ViewPropertyAnimator的信息可以参考PropertyAnimation. 还可以使用一个StateListAnimator通过声明的方式来指定这些动画. 该方法在状态修改触发的动画中很有用, 比如当用户点击了一个button. 更多的信息可以参考AnimateView State Changes.

Z值的单位是dp.

自定义View阴影和边框(OutLine):

View背景drawable的边框决定了它的默认阴影形状. 边框代表一个图形对象的外形并定义了触摸反馈的涟漪(ripple)区域. 假设有这样一个view, 它拥有一个背景drawable:

<TextView    android:id="@+id/myview"    ...    android:elevation="2dp"    android:background="@drawable/myrect" />

背景drawable定义为一个带有圆角的矩形:

<!-- 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就会拥有一个带有圆角的阴影, 因为背景drawable定义了view的边框. 提供一个自定义的边框会覆盖默认的view阴影的形状. 要定义自定义边框:

1.      继承ViewOutlineProvider类.

2.      重写getOutline()方法.

3.      通过View.setOutlineProvider()方法来分配新的边框provider.

可以使用Outline类中的方法创建带有圆角的椭圆形和矩形边框. 默认边框provider从view的背景中获得边框provider. 如果不需要阴影, 设置view的边框provider为null.

View裁剪:

裁剪view让我们可以简单的改变view的形状. 可以裁剪view以获取跟其它设计元素的一致性, 或者改变view的形状来响应用户的输入. 可以使用View.setClipToOutline()方法或者android:clipToOutline属性将view裁剪成它的边框区域. 只有矩形圆形和圆角矩形边框支持裁剪, 可以通过Outline.canClip()方法判断.

要裁剪一个view为drawable的形状, 设置drawable为view的背景, 并调用View.setClipToOutline()方法. 裁剪view是一种很昂贵的操作, 所以不要对裁剪的view使用动画(don'tanimate the shape you use to clip a view).

使用Drawable:

Drawable的这些能力可以帮助我们实现materialdesign:

l  Drawable着色.

l  突出颜色提取.

l  矢量drawable .

Drawable着色:

在Android 5.0及更高版本中, 我们可以为Bitmap和nine-patches着色. 可以使用color资源或者主题属性(比如”?android:attr/colorPrimary)为它们着色. 还可以使用setTint()来对BitmapDrawable,NinePatchDrawable或者VectorDrawable对象着色. 还可以通过android:ting和android:tintMode属性来设置着色.

从图片中提取突出颜色:

Android支持库r21及更高版本可以支持Palette类, 该类让我们可以从一张图片中提取突出颜色. 该类可以提取这些突出颜色:

l  Vibrant

l  Vibrant dark

l  Vibrant light

l  Muted

l  Muted dark

l  Muted light

要提取这些颜色, 在加载图片的后台线程中给Palette.generate()静态方法传递一个Bitmap对象. 如果不能使用这个线程, 则使用Palette.generateAsync()方法并提供一个监听器. 我们可以从图片中通过Palette类中的getter方法来提取颜色, 比如Palette.getVibrantColor().要使用Palette类, 需要添加如下依赖:

dependencies {    ...    compile 'com.android.support:palette-v7:21.0.0'}

更多信息可以参考这里.

创建矢量Drawable:

在Android 5.0及更高版本中, 可以定义矢量Drawable, 它在缩放的时候不会损失清晰度. 这样在不同的分辨率下就只需要一个资源文件. 要创建一个矢量图像, 得在<vector>XML元素中定义形状的细节. 下面的代码定义了一个心形的矢量图片:

<!-- 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中用VectorDrawable对象来表示矢量图像. 更多关于pathData的语法可以参考SVG Path reference.

 

参考: https://developer.android.com/training/material/index.html

 

0 0
原创粉丝点击