android 实现磨砂效果_Android上如何做出毛玻璃模糊的效果?

本文介绍了在Android上实现磨砂效果(毛玻璃模糊)的步骤和技术,包括使用ViewTreeObserver获取底层view的Bitmap和通过Renderscript或StackBlur算法进行模糊处理。详细探讨了两种模糊算法的性能和优化策略,提供了相关的源码实现。
摘要由CSDN通过智能技术生成

e694149541aa

上图展示了一种很典型的视觉效果——文字的背景不再是固定的,而是将底层的相应区域模糊化,好似盖了一层毛玻璃。

其原理也很简单,分为三步走:

获取底层的view的Bitmap——b1

将b1模糊化,保存为b2

把b2设为文字的背景。

里面涉及到的技术点有两个:

何时访问能获取到底层view的完整Bitmap?

如何模糊化,该采用什么算法?

技术点一:何时访问能获取到底层view的完整Bitmap?

ViewTreeObserver里面有一个监听器为OnPreDrawListener

// 当一个视图树将要绘制时,所要调用的回调函数的接口类

public interface OnPreDrawListener {

boolean onPreDraw();

}

当它执行时,布局文件经过了measured、laid out、displayed,即将被绘制到屏幕,此时调用它的getDrawingCache()方法可以获得其Bitmap。完整方法如下:

lowerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

@Override

public boolean onPreDraw() {

lowerView.getViewTreeObserver().removeOnPreDrawListener(this);

lowerView.buildDrawingCache();

Bitmap bmp = lowerView.getDrawingCache();

return true;

}

});

技术点二:如何模糊化,该采用什么算法?

方案有两种:

借助Renderscript做高斯模糊,本质上是做卷积计算。

采用StackBlur算法对图片进行模糊处理,相较于高斯模糊,计算量小了很多。

两种方案都可以进行对Bitmap对象的模糊处理,但当模糊半径增大时,StackBlur能够保持较好的性能,且不受Renderscript半径25px的限制。

在GitHub项目有一个项目blurring,其实现了StackBlur算法的Java实现版FastBlur,并给出两种方案效率对比demo。经过测试,

在Mac上Genymotion模拟器下运行Android4.4.4,Renderscript耗时42ms,FastBlur耗时82ms

在小米4真机上运行Android6.0.1,Renderscript耗时124ms,FastBlur耗时271ms

看起来,Renderscript的性能更好,应该是Android上对Renderscript做了优化。尽管如此,考虑到Android中渲染一帧的时间应该不超过16ms(60fps),这样的性能并不友好。blurring作者想出了另外一种思路:

把bitmap的尺寸先降低然后进行模糊处理,然后再放大尺寸

这时候,效率提升非常明显:

在Mac上Genymotion模拟器下运行Android4.4.4,Renderscript耗时5ms,FastBlur耗时1ms

在小米4真机上运行Android6.0.1,Renderscript耗时16ms,FastBlur耗时7ms。

生成的模糊图片当然有所不同,但是都是模糊背景,所以对用户而言没有太大差别。

好了,至此Android上制作毛玻璃背景模糊效果的技术都确定了。

源码

我在blurring基础上做了封装,接口如下:

/**

*

* @param context 上下文

* @param lowerView 底层view控件

* @param upperView 需要模糊背景的控件

*/

public static void doBlur(final Context context, final View lowerView, final View upperView) {

lowerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {

@Override

public boolean onPreDraw() {

lowerView.getViewTreeObserver().removeOnPreDrawListener(this);

lowerView.buildDrawingCache();

Bitmap bmp = lowerView.getDrawingCache();

doBlur(context, bmp, upperView, true);

return true;

}

});

}

相对应类有两个:

RSBlur

package com.paveldudka.util;

import android.annotation.TargetApi;

import android.c

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值