Android 5.x-使用Material Theme添Palette

Android 5.x--使用Material Theme加Palette

Android5.0较之以前的版本,有一个比较大的改变:在Android5.x中支持Material Design的主题风格,这对于视觉上将是一个重大的改变。新的主题风格给人的感觉眼前一亮,原来Android也可以这么美,相信通过不断完善,Android也将越来越强大。那么今天就介绍一下,如何使用这让人眼前一亮的主题吧。

开始使用

目前只有在Android5.0之上的版本才可以支持Material的主题风格,这样我们首先在res/values-v21/styles.xml文件中定义使用Material主题。

<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light">   
    </style>
</resources>

注意直接在values/styles.xml文件之中修改的话,编译器会提示:当前支持的最低的API版本中不存在该主题。

定制自己的主题

Android开发者官网中给出一张图片,形象的告诉我们Material主题所支持修改的颜色属性,方便我们定制自己的主题:

Android 5.x-使用Material Theme添Palette

这样我们就可以修改这些值来定制自己的主题了:

<resources>
    <style name="AppTheme" parent="android:Theme.Material.Light">
        <item name="android:colorPrimary">#00ffff</item>
        <item name="android:colorPrimaryDark">#0000ff</item>
        <item name="android:navigationBarColor">#0000ff</item>
        <item name="android:textColorPrimary">#fff</item>
    </style>
</resources>

在Android5.0的模拟器上运行一下吧,

Android 5.x-使用Material Theme添Palette

怎么样,连标题栏和底部的导航栏都可以改变颜色了,而且连Actionbar都和以前不一样了,是不是很酷炫。

同时Android也允许你使用android:statusBarColor属性,或者使用Window.setStatusBarColor方法快速设置状态栏的颜色。

适配较低的Android版本

一切都很好,只是我的主题只能在5.0之上的版本才能用吗,太扫兴了吧。别担心,谷歌当然也会为低版本提供支持,让我们看看怎么做吧。

1.在Android studio中,首先来增加下面的Gradle依赖模块到工程中来:

dependencies {
    ......
    compile 'com.android.support:appcompat-v7:22.0.0'
}

接着我们在values/style.xml文件中添加自己的主题,注意这时我们不再使用android:Theme.Material.XXX的主题,而是使用依赖库中的主题Theme.AppCompat.XXX,同时不再需要values-v21/style.xml中的android:Theme.Material.XXX主题。

<style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">#0ff</item>
        <item name="colorPrimaryDark">#00f</item>
        <item name="colorAccent">#fff</item>
</style>

测试中发现textColorPrimary属性的名称改为了colorAccent

2.在Eclipse中,我们需要升级到最新的ADT以及SDK,在WorkSpace中导入appcompat-v7的library工程,之后的使用步骤是一模一样的,大家可以试一试。

Palette的使用

同时,在Android 5.0中Google还发布了一个新的类Palette帮助我们提取Bitmap中颜色值,让我更方便的定制自己的主题,一起来看看吧。

这个类能提取以下突出的颜色:

  • Vibrant(清爽的)
  • Vibrant dark(清爽的暗色)
  • Vibrant light(清爽的亮色)
  • Muted(柔和的)
  • Muted dark(柔和的暗色)
  • Muted lighr(柔和的亮色)

使用Palette

首先在使用之前,我们需要引用该依赖库到我们的工程中来:

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

通过调用Palette的静态方法generate或generateAsync可以帮助我们提取颜色值,提取颜色的过程必须在异步线程中执行。

注意,generate方法不允许在主线程中调用,如果自己没有使用异步线程,可以使用generateAsync方法去帮助我们开启一个异步线程,并监听回调事件。

Palette.generateAsync(bitmap,
        new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(Palette palette) {
         Palette.Swatch vibrant =
                 palette.getVibrantSwatch();
          if (vibrant != null) {
              // If we have a vibrant color
             .......
          }
    }
});

从View获得Bitmap

传入的对象必须是一个Bitmap对象,那么如何从一个View转化为Bitmap呢,我们可以通过画布绘制来实现:

private Bitmap getViewBitmap(View v) {
    v.clearFocus();
    v.setPressed(false);

    boolean willNotCache = v.willNotCacheDrawing();
    v.setWillNotCacheDrawing(false);

    int color = v.getDrawingCacheBackgroundColor();
    v.setDrawingCacheBackgroundColor(0);

    if (color != 0) {
        v.destroyDrawingCache();
    }
    v.buildDrawingCache();
    Bitmap cacheBitmap = v.getDrawingCache();
    if (cacheBitmap == null) {
        return null;
    }
    Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
    // Restore the view
    v.destroyDrawingCache();
    v.setWillNotCacheDrawing(willNotCache);
    v.setDrawingCacheBackgroundColor(color);
    return bitmap;
}

接下来我们来用一下吧,通过提取Activity的整个布局中较安的柔和颜色,并把它设置给状态栏上。

package com.example.acer.materialtest;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.support.v7.graphics.Palette;
import android.view.View;
import android.widget.LinearLayout;


public class MainActivity extends ActionBarActivity {

    private LinearLayout containLayout;

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

        containLayout = (LinearLayout) findViewById(R.id.contain_layout);
        Bitmap bitmap = getViewBitmap(containLayout);
        if (bitmap != null)
            Palette.generateAsync(bitmap,
                    new Palette.PaletteAsyncListener() {
                        @Override
                        public void onGenerated(Palette palette) {
                            Palette.Swatch swatch =
                                    palette.getDarkMutedSwatch();
                            if (swatch != null) {
                               getWindow().setStatusBarColor(swatch .getRgb());
                            }
                        }
                    });

    }

    private Bitmap getViewBitmap(View v) {
        v.clearFocus();
        v.setPressed(false);

        boolean willNotCache = v.willNotCacheDrawing();
        v.setWillNotCacheDrawing(false);

        // Reset the drawing cache background color to fully transparent
        // for the duration of this operation
        int color = v.getDrawingCacheBackgroundColor();
        v.setDrawingCacheBackgroundColor(0);

        if (color != 0) {
            v.destroyDrawingCache();
        }
        v.buildDrawingCache();
        Bitmap cacheBitmap = v.getDrawingCache();
        if (cacheBitmap == null) {
            return null;
        }
        Bitmap bitmap = Bitmap.createBitmap(cacheBitmap);
        // Restore the view
        v.destroyDrawingCache();
        v.setWillNotCacheDrawing(willNotCache);
        v.setDrawingCacheBackgroundColor(color);
        return bitmap;
    }

}

效果如下:

Android 5.x-使用Material Theme添Palette