前言 如题,本文模仿实现有道云笔记的侧滑菜单中的头像背景的效果,这一效果可用借鉴使用,毕竟大多数时候我们在应用上的资料可能没有像play、微博等的个人页面的自定义背景图。没用过这款应用的童鞋可以下载这款应用看看。
分析 先来看看有道云笔记上的图片(重点是头像上的背景图,真机看起来效果比较好):
有道云笔记效果图
在手机上没找到背景的效果图,应该是在手机上生成的效果图,根据它的背景图片可以看出图片时黑白的而且是有点朦胧感,所以经过分析和实验得到做这一效果可以使用的方法:黑白效果用ColorFilter
实现、模糊效果可以用RenderScript
的API实现。代码的步骤也是先得到黑白的Bitmap再把它模糊处理。
黑白 Android中图片是以RGBA像素点的形式加载到内存中的,这些像素信息通过ColorMatrix ,官方文档的描述如下: 4×5矩阵转换位图的颜色+ alpha分量。该矩阵存储在一个单独的阵列中,其进行如下处理:1
2
3
4
[ a, b, c, d, e,
f, g, h, i, j,
k, l, m, n, o,
p, q, r, s, t ]
当应用于ColorR,G,B,A ,所以将上面矩阵跟图片的原值相乘后的结果:1
2
3
4
R' = a*R + b*G + c*B + d*A + e;
G' = f*R + g*G + h*B + i*A + j;
B' = k*R + l*G + m*B + n*A + o;
A' = p*R + q*G + r*B + s*A + t;
所以ColorMatrix经ColorFilter 就可以在Android中处理图片的颜色,关于这两个类更详尽的信息可以自己继续Google一下。而把图片变黑白就简单一些了,直接通过ColorMatrix的setSaturation )方法更改图片的饱和度即可,我们知道当图片的饱和度为0时就会变为黑白了。此外我们也可麻烦一点自己通过ColorMatrix调出一个合适的值也可以,这也是ColorMatrix的强大之处,下面是黑白效果的ColorMatrix的值:1
2
3
4
5
6
float [] src = new float []{
0.28F , 0.60F , 0.40F , 0 , 0 ,
0.28F , 0.60F , 0.40F , 0 , 0 ,
0.28F , 0.60F , 0.40F , 0 , 0 ,
0 , 0 , 0 , 1 , 0 ,
};
所以黑白部分的处理代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Drawable drawable = getResources().getDrawable(R.drawable.rocko);
Bitmap srcBitmap = BitmapUtils.drawable2Bitmap(drawable);
float [] src = new float []
{
0.28F , 0.60F , 0.40F , 0 , 0 ,
0.28F , 0.60F , 0.40F , 0 , 0 ,
0.28F , 0.60F , 0.40F , 0 , 0 ,
0 , 0 , 0 , 1 , 0 ,
};
ColorMatrix cm = new ColorMatrix(src);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
Bitmap resultBitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint paint = new Paint();
paint.setAntiAlias(true );
paint.setAlpha(100 );
paint.setColorFilter(f);
canvas.drawBitmap(srcBitmap, 0 , 0 , paint);
模糊 模糊的效果处理可以有几种方式:Java、jni、Android的RenderScript API,Java代码的一种比较快的一种模糊算法实现fastBlur 效果不太理想,还是比RenderScript
慢些,所以最终采用Android官方的API实现RenderScript support v8的支持包 ,Android support v8支持包是在...\build-tools\21.1.2\renderscript
SDK的这里的,在Android Studio中使用support v8:在build.gradle的defaultConfig中加上下面两句即可,1
2
renderscriptTargetApi 21
renderscriptSupportModeEnabled true
所以模糊部分的处理:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Bitmap bB = BitmapUtils.blurBitmap(getApplicationContext(), resultBitmap, 15.5f );
public static Bitmap blurBitmap (Context applicationContext, Bitmap bitmap, float radius)
{
Bitmap outBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
RenderScript rs = RenderScript.create(applicationContext);
ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation allIn = Allocation.createFromBitmap(rs, bitmap);
Allocation allOut = Allocation.createFromBitmap(rs, outBitmap);
blurScript.setRadius(radius);
blurScript.setInput(allIn);
blurScript.forEach(allOut);
allOut.copyTo(outBitmap);
bitmap.recycle();
rs.destroy();
return outBitmap;
}
工作完成,最后要注意的是模糊效果的处理是比较耗时的(~250ms),所以在UI线程里直接处理的话肯定会掉帧,16ms是界限值,建议开线程预先处理好再设置。仿照的效果图如下:
仿照效果图
End 本文demo地址