Android5.0新特性-Material Design

概述

2014年,Google携Android5.X重装归来,全新的UI设计和更加优化的性能,令开发者眼前一亮

安装和配置Android5.0开发环境

开发Android还得靠AS,下载地址
http://developer.android.com/intl/zh-cn/sdk/index.html
Android5.0新特性-Material Design_第1张图片

材料设计概述

材料的形态模拟

Google通过模拟自然界纸墨的形态变化、光线与阴影、纸与纸之间的控件层级关系,带来一种真实的空间感

更加真实的动画

Android5.x大量加入了各种新的动画效果,让整个设计风格更加自然和谐。

大色块的使用

Material Desigin中运用了大量高度饱和、适中亮度的大色块来突出界面的主次,并一扫Android4.X系列Holo主题的沉重感,让界面更加富有时尚感和视觉冲击力

此外还有很多新的设计风格,如悬浮按钮,聚焦大图、无框按钮、波纹效果等新特性
具体可参考
http://www.google.com/design/#resources

材料设计能做哪些工作

  • 保证向后的兼容性
  • 使用材料设计的主题
  • 让视图产生阴影
  • 使用RecyclerView和CardView
  • 定制动画

intel x86模拟器

下载和安装intel x86模拟器加速器

之前的ARM模拟器,是以软件的形式模拟,所以很慢~x86可以选这使用宿主机器的GPU等,和真机的速度相差无几~

下面更新SDK使用了国内的代理,需要的童鞋可以看下
Android5.0新特性-Material Design_第2张图片

下载

打开SDK Manager
Android5.0新特性-Material Design_第3张图片

install 之后
这里写图片描述

安装

找到SDK如下目录,因为这个加速器是跨平台的,windows操作系统对应的是exe执行文件,安装即可
Android5.0新特性-Material Design_第4张图片

Android5.0新特性-Material Design_第5张图片

当然你也可以使用genymotion~有真机最好了~

从官方下载x86模拟器加速器

除了从SDK中下载,还可以从Intel官方网站上下载加速器

官网如下:
https://software.intel.com/zh-cn/android

https://software.intel.com/zh-cn/android/articles/intel-hardware-accelerated-execution-manager/

Android5.0新特性-Material Design_第6张图片

检测 Intel X86模拟器加速器是否安装成功

Android5.0新特性-Material Design_第7张图片

cmd命令行窗口:

Android5.0新特性-Material Design_第8张图片

安装x86模拟器镜像

虽然我们上面安装了加速器,但是只是模拟器而已,镜像才是关键!!!

从SDK中直接安装

官方推荐的安装方法

因为我的电脑操作系统是64位,我们打算在5.0的模拟器中使用,所以选择如下:
Android5.0新特性-Material Design_第9张图片

从Intel官方下载安装

https://software.intel.com/zh-cn/android/articles/android-44-kitkat-x86-emulator-system-image

指导文档

下载后放到相应的目录即可~

体验以x86模式运行Android模拟器

Android5.0新特性-Material Design_第10张图片

都是默认选项,选择使用宿主机器的GPU~
Android5.0新特性-Material Design_第11张图片

哈哈 速度那是必须的快~

Material主题

Material Design现在有三种默认的主题可以设置:

  1. @android:style/Theme.Material (dark version)
  2. @android:style/Theme.Material.Ligh (ligth version)
  3. @android:style/Theme.Material.Ligh.DarkActionBar

同时 Android5.x提出了Color Palette (颜色调色板)的概念,让开发者可以自己设定系统区域的颜色,使整个APP的颜色风格和系统的颜色风格保持一致。

通过如下代码,可以通过使用自定义Style的方式来创建自己的Color Palette 颜色主题,从而实现不同的颜色风格。

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="AppTheme" parent="android:Theme.Material"> <!--appBar的颜色--> <item name="android:colorPrimary">#BEBEBE</item> <!--状态栏的颜色--> <item name="android:colorPrimaryDark">#FF5AEBFF</item> <item name="android:navigationBarColor">#FFFF4130</item> <item name="android:colorAccent">#BF3EFF</item> </style>
</resources>


Android5.0新特性-Material Design_第12张图片

RecyclerView

控件简介

  • ListView的升级版
  • LinearLayoutManager
  • GridLayoutManager
  • StaggeredGridLayoutManager
  • 定制Item动画,指定Item之间的分隔线

添加RecyclerView控件依赖包

Android Studio开发工具,在本项目的build.gradle文件中添加

  compile 'com.android.support:recyclerview-v7:23.1.1'

如果是eclipse的话,下载jar包,放到lib下,一般都会自动的build path,检查下即可。

如何下载jar ?
在SDK Manager中下载Support Library

sdk\extras\android\support\v7\recyclerview\libs

工程结构

Android5.0新特性-Material Design_第13张图片

为Recycler准备数据

package demo.turing.com.materialdesignwidget.recyclerView;

import java.util.ArrayList;

import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;

/** * MyApp * * @author Mr.Yang on 2016-03-30 20:21. * @version 1.0 * @desc */
public class SimulatorData {


    public static ArrayList<SampleModel> getSampleModelData(int size) {

        ArrayList<SampleModel> sampleData = new ArrayList<SampleModel>(size);

        for (int i = 0; i < size; i++) {
            sampleData.add(new SampleModel("新的列表项< " + i + " >"));
        }

        return sampleData;
    }

}
package demo.turing.com.materialdesignwidget.recyclerView.model;

/** * MyApp * * @author Mr.Yang on 2016-03-30 20:23. * @version 1.0 * 对应Item中药显示的数据项 */
public class SampleModel {



    private String text;


    public SampleModel(String text) {
        this.text = text;
    }


    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

绘制列表项之间的分隔线

Android5.0新特性-Material Design_第14张图片

package demo.turing.com.materialdesignwidget.recyclerView;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/** * MyApp * * @author Mr.Yang on 2016-03-30 20:37. * @version 1.0 * 分隔条 */
public class SampleDivider extends RecyclerView.ItemDecoration {

    // 默认分隔条Drawable资源的ID,使用系统自带的
    private static final int[] ATTRS = {android.R.attr.listDivider};
    // 分隔条Drawable对象
    private Drawable mDivider;


    /** * 构造函数 * @param context */
    public SampleDivider(Context context) {
        // 使用TypedArray装载定义的ATTRS
        TypedArray a = context.obtainStyledAttributes(ATTRS);
        // 获取系统提供的分隔条Drawable对象
        mDivider = a.getDrawable(0);
        // 回收TypedArray所占用的空间
        a.recycle();
    }

    /** * 在该方法中绘制了所有列表项之间的分隔条, * 将分隔条看做是一个非常非常窄的矩形,每个Item的左右是一样的,只是上下不同, * 在for循环中计算top和bottom */
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent) {
        // 获取列表项距离左边缘的距离
        int left = parent.getPaddingLeft();

        // 获取列表项距离右边缘的距离
        int right = parent.getWidth() - parent.getPaddingRight();

        // 获取列表项的总数
        int childCount = parent.getChildCount();

        // 开始绘制所有列表项之间的分隔线
        for (int i = 0; i < childCount; i++) {
            // 获得当前的列表项
            View child = parent.getChildAt(i);

            // 获取当前列表项的布局参数信息
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
                    .getLayoutParams();

            // 计算分隔条左上角的纵坐标
            int top = child.getBottom() + params.bottomMargin;

            // 计算分隔条右下角的纵坐标
            int bottom = top + mDivider.getIntrinsicHeight();

            // 设置分隔条绘制的位置
            mDivider.setBounds(left, top, right, bottom);

            // 开始绘制当前列表项下方的分隔条
            mDivider.draw(c);

        }

    }

}

实现Adapter

package demo.turing.com.materialdesignwidget.recyclerView.adapter;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Random;

import demo.turing.com.materialdesignwidget.R;
import demo.turing.com.materialdesignwidget.recyclerView.SimulatorData;
import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;

/** * MyApp * * @author Mr.Yang on 2016-03-30 21:03. * @version 1.0 * @desc */
public class SampleRecyclerAdapter extends RecyclerView.Adapter<SampleRecyclerAdapter.ViewHolder> {

    // 模拟数据
    private final ArrayList<SampleModel> sampleData = SimulatorData.getSampleModelData(20);

    /** * 用于创建控件 * * @param parent * @param viewType * @return */
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        // 获得列表项控件(LinearLayer对象)

        // list_basic_item.xml布局文件中只包含一个<LinearLayer>标签,
        // 在该标签中包含了一个<TextView>标签, item是LinearLayout对象
        View item = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.list_basic_item, parent, false);

        return new ViewHolder(item);
    }

    /** * 为控件设置数据 * * @param holder * @param position */
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        // 获取当前item中显示的数据
        final SampleModel rowData = sampleData.get(position);

        // 设置要显示的数据
        holder.textViewSample.setText(rowData.getText());
        // 设置tag
        holder.itemView.setTag(rowData);

    }


    @Override
    public int getItemCount() {
        return sampleData.size();
    }


    /** * 删除指定的Item * @param position */
    public void removeData(int position) {
        sampleData.remove(position);
        // 通知RecyclerView控件某个Item已经被删除
        notifyItemRemoved(position);

    }


    /** * 在指定位置添加一个新的Item * @param positionToAdd */
    public void addItem(int positionToAdd) {
        sampleData.add(positionToAdd, new SampleModel("新的列表项" + new Random().nextInt(10000)));
        // 通知RecyclerView控件插入了某个Item
        notifyItemInserted(positionToAdd);
    }


    /** * 对应Item中的控件 */
    public static class ViewHolder extends RecyclerView.ViewHolder {

        private final TextView textViewSample;

        public ViewHolder(View itemView) {
            super(itemView);
            textViewSample = (TextView) itemView
                    .findViewById(R.id.textViewSample);
        }
    }


}

完成使用RecyclerView控件的最后工作

package demo.turing.com.materialdesignwidget.recyclerView;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

import demo.turing.com.materialdesignwidget.R;
import demo.turing.com.materialdesignwidget.recyclerView.adapter.SampleRecyclerAdapter;

public class RecyclerViewAct extends AppCompatActivity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view);

        // 获取RecyclerView对象
        final RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);

        // 创建线性布局管理器(默认是垂直方向)
        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);

        // 为RecyclerView指定布局管理对象
        recyclerView.setLayoutManager(layoutManager);

        // 创建列表项分隔线对象
        final RecyclerView.ItemDecoration itemDecoration = new SampleDivider(this);

        // 为RecyclerView控件指定分隔线对象
        recyclerView.addItemDecoration(itemDecoration);

        final SampleRecyclerAdapter sampleRecyclerAdapter = new SampleRecyclerAdapter();
        recyclerView.setAdapter(sampleRecyclerAdapter);


    }


}

效果图

Android5.0新特性-Material Design_第15张图片

立体卡片CardView

Code

package demo.turing.com.materialdesignwidget.cardView;

import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.widget.SeekBar;
import android.widget.Toast;

import demo.turing.com.materialdesignwidget.R;

public class CardViewAct extends AppCompatActivity {


    private CardView mCardView;

    private SeekBar mRadiusSeekBar,mElevationSeekBar;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_card_view);
        mCardView = (CardView)findViewById(R.id.cardview);
        mRadiusSeekBar = (SeekBar)findViewById(R.id.cardview_radius_seekbar);
        mRadiusSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener()
        {

            @Override
            public void onStopTrackingTouch(SeekBar seekBar)
            {
                // TODO Auto-generated method stub

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar)
            {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress,
                                          boolean fromUser)
            {
                mCardView.setRadius(progress);

            }
        });


        mElevationSeekBar = (SeekBar)findViewById(R.id.cardview_elevation_seekbar);
        mElevationSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub

            }

            /** * 加了 @TargetApi(Build.VERSION_CODES.LOLLIPOP) * 在API21上运行时没有问题的,但是低版本的会报错,最好做下判断 * @param seekBar * @param progress * @param fromUser */

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress,
                                          boolean fromUser) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    mCardView.setElevation(progress);
                } else{
                    Toast.makeText(CardViewAct.this,"5.0以下版本不支持~",Toast.LENGTH_SHORT).show();
                }

            }
        });

    }
}
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">

    <LinearLayout  android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin">

        <android.support.v7.widget.CardView  android:id="@+id/cardview" android:layout_width="fill_parent" android:layout_height="160dp" android:layout_marginLeft="@dimen/margin_large" android:layout_marginRight="@dimen/margin_large" android:elevation="100dp" card_view:cardBackgroundColor="@color/cardview_initial_background" card_view:cardCornerRadius="8dp" >

            <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_margin="@dimen/margin_medium" android:text="@string/cardview_contents" />


        </android.support.v7.widget.CardView>


        <LinearLayout  android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/margin_large" android:orientation="horizontal">

            <TextView  android:layout_width="@dimen/seekbar_label_length" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/cardview_radius_seekbar_text" />

            <SeekBar  android:id="@+id/cardview_radius_seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/margin_medium" />
        </LinearLayout>

        <LinearLayout  android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal">

            <TextView  android:layout_width="@dimen/seekbar_label_length" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:text="@string/cardview_elevation_seekbar_text" />

            <SeekBar  android:id="@+id/cardview_elevation_seekbar" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/margin_medium" />
        </LinearLayout>
    </LinearLayout>

</ScrollView>

效果图

Android5.0新特性-Material Design_第16张图片

视图和阴影

Material Design的一个很重要的特性就是拟物扁平化。
Android5.0新特性-Material Design_第17张图片

影响视图阴影的因素

以往的Android View通常有2个属性——X和Y,而在Android5.X中,Google为其增加了一个新的属性 —Z,对应垂直方向上的高度变化。

在Android5.x中,View的Z值由 elevation + translationZ(这两个都是5.x引入的新特性)组成。

其中 elevation是静态的成员,translationZ可以在代码中使用来实现动画的效果。

Z = elevation + translationZ

通过布局文件和Java代码设置视图的阴影

通过布局文件设置

在xml中设置View的视图高度

android:elevation="Xxdp"

比如:

 <TextView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/cardview_contents" android:elevation="10dp" />

通过Java代码设置

view.setTranslationZ(XXX)

通常也会使用属性动画来为视图高度改变的时候增加一个动画效果

if(flag){
    view.animate().translationZ(100);
    flag=false;
}else{
    view.animate().translationZ(0);
    flag=true;
}

阴影拖动

视图裁剪

着色

ripple_drawable资源

矢量drawable资源

在Android中使用SVG矢量图

SVG设计器

实现SVG矢量动画

APP的兼容性

你可能感兴趣的:(android,design,material,5-x)