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;
}
}
效果如下: