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主题所支持修改的颜色属性,方便我们定制自己的主题:
这样我们就可以修改这些值来定制自己的主题了:
<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的模拟器上运行一下吧,
怎么样,连标题栏和底部的导航栏都可以改变颜色了,而且连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; } }
效果如下: