本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
现在,越来越多的App里面使用了模糊效果,我尤其喜欢雅虎天气的界面,上滑的时候背景图片会跟着移动,最重要的是背景图片会根据手指上下移动的距离来进行不同程度的模糊,感觉甚为惊奇,毕竟大家都知道,在Android平台上进行模糊渲染是一个相当耗CPU也相当耗时的操作,一旦处理不好,卡顿是在所难免的。虽然我并不知道雅虎天气是怎么做出这种效果的,但是简单的模仿一下的话,还是能做到的。
一般来说,考虑到效率,渲染一张图片最好的方法是使用OpenGL,其次是使用C++/C,使用Java代码是最慢的。但是Android推出RenderScript之后,我们就有了新的选择,测试表明,使用RenderScript的渲染效率和使用C/C++不相上下,但是使用RenderScript却比使用JNI简单地多!同时,Android团队提供了RenderScript
的支持库,使得在低版本的Android平台上也能使用。
不过在使用RenderScript之前,对于模糊一张图片,需要注意的是,我们应该尽量不要使用原尺寸分辨率的图片,最好将图片缩小比例,这小渲染的效率要高一些。
动态模糊的实现
如何使用RenderScript来模糊一张图片呢?废话不多说,先上核心代码:
1 | public class BlurBitmap { |
完成上面的代码后,需要在app的gradle文件中添加如下的支持:
1 | defaultConfig { |
代码做了简单的注释以帮助理解,如果需要详细了解,可以查阅官方文档:RenderScript
然后,我们可以看一下模糊前和模糊后的效果对比:
将图片模糊后,接下来要考虑的是怎么实现动态模糊
效,有一点需要注意的是,即使我们使用了RenderScript
这种高效的渲染方式,但是在实际测试中,渲染一张500*700分辨率的PNG格式图片,在我的Pro 6手机上,仍然需要50ms左右的时间,显然如果使用上面的代码进行实时渲染的话,会造成界面严重的卡顿。
既然实时渲染这条路走不通,那么就需要我们另辟蹊径了,我这里可以提供一种方法:先将图片进行最大程度的模糊处理,再将原图放置在模糊后的图片上面,通过不断改变原图的透明度(Alpha值)来实现动态模糊效果。
简单的代码如下:
1 | public class MainActivity extends AppCompatActivity { |
xml布局文件代码如下:
1 | <?xml version="1.0" encoding="utf-8"?> |
效果如下:
怎么样?是不是很简单的样子?只需要调用模糊处理方法,并在SeekBar的滑动监听里面调用原图像的setAlpha()
方法,来实现动态模糊效果。
你以为这样就完了?不不不,我们的目的并不是这么单纯,哦,不对,并不是这么简单。还记得文章开头的时候说了吗?我们的终极目的是要简单地模仿一下雅虎天气的界面效果。
仿雅虎天气界面
有了上面的基础,就可以很容易地模仿雅虎天气的界面效果。简单来说,在上面制作出的效果基础上,有以下两点需要注意的地方:
- 需要要监听滑动事件,然后再将背景图片调用
setTop()
方法,将图片向上平移一段距离。 - 要向上平移图片,还需要手动增加图片的高度,不然图片向上平移后,底部就会有留白。设置图片高度的核心代码如下:
1 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); |
完成上面两点的内容后,基本就可以模仿出雅虎天气的首页了。
结合第一个例子的demo,效果如下:
相关代码已上传至Github:BlurredView,欢迎Star,Fork。
本着不重复造轮子的原则,我将模糊图像的代码上传至JCenter,大家只需要在项目中添加Gradle引用就行了,具体使用方法请参考上面Github仓库的ReadMe。