大家应该都看到过iOS7解锁屏幕的滑动模糊渐变效果,好了,现在可以把手纸收起来了,今天黄老师就给大家讲一下如何在Android平台上
实现类似的滑动模糊渐变效果,其实方式远比你想像的简单。
目标效果展示:



第一部分:几个前提
说到模糊效果,我们先要了解几个前提
1、原图,指需要被模糊的一张位图
2、模糊,通常是采用指将一个位图的每个像素RGB值都取周围像素的RGB值的平均值,这样就可以产生模糊效果,一般通过高斯函数来实现,
至于Java中的实现方式黄老师就不给大家细讲了,我也不是搞图形算法的,在这方面了解的不比大家多,百度一下能找到一堆高斯模糊转换的实现。
3、模糊半径,指每个像素点周围模糊的半径,半径越大,模糊程度约高,模糊效果越明显,同时,模糊计算耗费时间越长。
4、模糊处理非常费时,一半在100ms~5000ms内,就黄老师我本人找的网上的算法实测,一般android通过java实现的高斯模糊算法转换一张手机
屏幕分辨率为480x800的位图需要2s左右,所以如果要在滑动的过程中实时不断重新计算模糊效果会非常差,所以如果要实现iOS7那样的滑动动态模糊
渐变效果,用这样的方式是不可行的,实际上iOS也不是这么做的,因为iOS的硬件也没达到能实时计算的程度。
那么究竟应该如何去实现模糊渐变呢,其实非常简单,我们接着讲。
第二部分:动态模糊渐变的合理实现方式
其实,我的方式非常简单,首先你需要明确一个最大的模糊效果的模糊半径值,我们给它取个名字叫maxRadius,然后使用maxRadius和原图传入高斯模糊算法
中计算出最大模糊效果的位图maxBlurBitmap。
然后,在ui组件中,假设我的原图是用一个ImageView显示在界面上的,然后你所需要做的是,再创建一个ImageView置于原图ImageView之上,然后将图片源
设置为maxBlurBitmap,如下图:

接着,我们只需要简单的调整maxBlurBitmap的透明度,即可实现模糊渐变效果了,是否很简单呢?
第三部分,提供一个最简单的Java高斯模糊实现,我网上找来的,方便偷懒不愿自己找的同学
001.
1 /**
002.
2 * 位图处理类
003.
3 * @author HalfmanG2
004.
4 */
005.
5 public class BitmapUtil {
006.
6
007.
7 /**
008.
8 * 创建一个虚化的位图
009.
9 * @param sentBitmap 原位图
010.
10 * @param radius 虚化半径
011.
11 * @return 虚化后的位图
012.
12 */
013.
13 public static Bitmap createBlurBitmap(Bitmap sentBitmap,int radius) {
014.
14 Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(),true);
015.
15 if (radius <1) {
016.
16 return (null);
017.
17 }
018.
18 int w = bitmap.getWidth();
019.
19 int h = bitmap.getHeight();
020.
20 int[] pix =new int[w * h];
021.
21 bitmap.getPixels(pix,0, w,0,0, w, h);
022.
22 int wm = w -1;
023.
23 int hm = h -1;
024.
24 int wh = w * h;
025.
25 int div = radius + radius +1;
026.
26 int r[] =new int[wh];
027.
27 int g[] =new int[wh];
028.
28 int b[] =new int[wh];
029.
29 int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
030.
30 int vmin[] =new int[Math.max(w, h)];
031.
31 int divsum = (div +1) >>1;
032.
32 divsum *= divsum;
033.
33 int dv[] =new int[256 * divsum];
034.
34 for (i =0; i <256 * divsum; i++) {
035.
35 dv[i] = (i / divsum);
036.
36 }
037.
37 yw = yi =0;
038.
38 int[][] stack =new int[div][3];
039.
39 int stackpointer;
040.
40 int stackstart;
041.
41 int[] sir;
042.
42 int rbs;
043.
43 int r1 = radius +1;
044.
44 int routsum, goutsum, boutsum;
045.
45 int rinsum, ginsum, binsum;
046.
46 for (y =0; y < h; y++) {
047.
47 rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum =0;
048.
48 for (i = -radius; i <= radius; i++) {
049.
49 p = pix[yi + Math.min(wm, Math.max(i,0))];
050.
50 sir = stack[i + radius];
051.
51 sir[0] = (p &0xff0000) >>16;
052.
52 sir[1] = (p &0x00ff00) >>8;
053.
53 sir[2] = (p &0x0000ff);
054.
54 rbs = r1 - Math.abs(i);
055.
55 rsum += sir[0] * rbs;
056.
56 gsum += sir[1] * rbs;
057.
57 bsum += sir[2] * rbs;
058.
58 if (i >0) {
059.
59 rinsum += sir[0];
060.
60 ginsum += sir[1];
061.
61 binsum += sir[2];
062.
62 }else {
063.
63 routsum += sir[0];
064.
64 goutsum += sir[1];
065.
65 boutsum += sir[2];
066.
66 }
067.
67 }
068.
68 stackpointer = radius;
069.
69 for (x =0; x < w; x++) {
070.
70 r[yi] = dv[rsum];
071.
71 g[yi] = dv[gsum];
072.
72 b[yi] = dv[bsum];
073.
73 rsum -= routsum;
074.
74 gsum -= goutsum;
075.
75 bsum -= boutsum;
076.
76 stackstart = stackpointer - radius + div;
077.
77 sir = stack[stackstart % div];
078.
78 routsum -= sir[0];
079.
79 goutsum -= sir[1];
080.
80 boutsum -= sir[2];
081.
81 if (y ==0) {
082.
82 vmin[x] = Math.min(x + radius +1, wm);
083.
83 }
084.
84 p = pix[yw + vmin[x]];
085.
85 sir[0] = (p &0xff0000) >>16;
086.
86 sir[1] = (p &0x00ff00) >>8;
087.
87 sir[2] = (p &0x0000ff);
088.
88 rinsum += sir[0];
089.
89 ginsum += sir[1];
090.
90 binsum += sir[2];
091.
91 rsum += rinsum;
092.
92 gsum += ginsum;
093.
93 bsum += binsum;
094.
94 stackpointer = (stackpointer +1) % div;
095.
95 sir = stack[(stackpointer) % div];
096.
96 routsum += sir[0];
097.
97 goutsum += sir[1];
098.
98 boutsum += sir[2];
099.
99 rinsum -= sir[0];
100.
100 ginsum -= sir[1];
101.
101 binsum -= sir[2];
102.
102 yi++;
103.
103 }
104.
104 yw += w;
105.
105 }
106.
106 for (x =0; x < w; x++) {
107.
107 rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum =0;
108.
108 yp = -radius * w;
109.
109 for (i = -radius; i <= radius; i++) {
110.
110 yi = Math.max(0, yp) + x;
111.
111 sir = stack[i + radius];
112.
112 sir[0] = r[yi];
113.
113 sir[1] = g[yi];
114.
114 sir[2] = b[yi];
115.
115 rbs = r1 - Math.abs(i);
116.
116 rsum += r[yi] * rbs;
117.
117 gsum += g[yi] * rbs;
118.
118 bsum += b[yi] * rbs;
119.
119 if (i >0) {
120.
120 rinsum += sir[0];
121.
121 ginsum += sir[1];
122.
122 binsum += sir[2];
123.
123 }else {
124.
124 routsum += sir[0];
125.
125 goutsum += sir[1];
126.
126 boutsum += sir[2];
127.
127 }
128.
128 if (i < hm) {
129.
129 yp += w;
130.
130 }
131.
131 }
132.
132 yi = x;
133.
133 stackpointer = radius;
134.
134 for (y =0; y < h; y++) {
135.
135 pix[yi] = (0xff000000 & pix[yi] ) | ( dv[rsum] <<16 ) | ( dv[gsum] <<8 ) | dv[bsum];
136.
136 rsum -= routsum;
137.
137 gsum -= goutsum;
138.
138 bsum -= boutsum;
139.
139 stackstart = stackpointer - radius + div;
140.
140 sir = stack[stackstart % div];
141.
141 routsum -= sir[0];
142.
142 goutsum -= sir[1];
143.
143 boutsum -= sir[2];
144.
144 if (x ==0) {
145.
145 vmin[y] = Math.min(y + r1, hm) * w;
146.
146 }
147.
147 p = x + vmin[y];
148.
148 sir[0] = r[p];
149.
149 sir[1] = g[p];
150.
150 sir[2] = b[p];
151.
151 rinsum += sir[0];
152.
152 ginsum += sir[1];
153.
153 binsum += sir[2];
154.
154 rsum += rinsum;
155.
155 gsum += ginsum;
156.
156 bsum += binsum;
157.
157 stackpointer = (stackpointer +1) % div;
158.
158 sir = stack[stackpointer];
159.
159 routsum += sir[0];
160.
160 goutsum += sir[1];
161.
161 boutsum += sir[2];
162.
162 rinsum -= sir[0];
163.
163 ginsum -= sir[1];
164.
164 binsum -= sir[2];
165.
165 yi += w;
166.
166 }
167.
167 }
168.
168 bitmap.setPixels(pix,0, w,0,0, w, h);
169.
169 return (bitmap);
170.
170 }
171.
171 }