Android 高斯模糊(1) 窗口模糊及java侧基本流程简述

Android 12起,原生支持了窗口模糊接口能力。

Window blurs | Android Open Source Project

按照官方的描述分为以下两种

  1. blur behind :使窗口后面的整个屏幕变得模糊

  2. background blur :使指定区域的底层内容模糊

其本质都是对当前surface后面的surface进行模糊显示。

blur behind

公开接口可通过主题配置或者代码设置,两种方式任选其一

xml 复制代码
<style name="BlurBehind" parent="Theme.CarLauncher">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBlurBehindEnabled">true</item>
    <item name="android:windowBlurBehindRadius">70dp</item>
</style>
kotlin 复制代码
// 代码方式设置
window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
window.attributes = window.attributes.apply {
 blurBehindRadius = 70
} 

blurBehindRadius参数会传递到system_server端 WindowState中,由Dimmer设置(新建了一个dimLayer),最终是调用

setBackgroundBlurRadius 接口

background blur

xml 复制代码
<style name="BackgroundBlur" parent="Theme.CarLauncher">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackgroundBlurRadius">70dp</item>
</style>
kotlin 复制代码
// 代码方式设置
 window.setBackgroundBlurRadius(70)

setBackgroundBlurRadius时做了什么事?

仅仅是创建了一个BackgroundBlurDrawable并设置到DecorView的背景中

BackgroundBlurDrawable

BackgroundBlurDrawable到底做了什么神奇的事情实现了背景高斯模糊?

BackgroundBlurDrawable代码只有短短几百行,相对比较简单,

核心只是:记录下模糊参数:坐标范围,圆角值,模糊半径,透明度。

圆角值,模糊半径,透明度都可以通过BackgroundBlurDrawable公开接口设置,不多解释。

坐标范围是通过监听RenderNode位置变化获得

Aggregator可以保存多个BackgroundBlurDrawable,也就是说:

一个窗口上是可以使用多个BackgroundBlurDrawable

一个ViewRootImpl对应一个Aggregator,Aggregator对应多个BackgroundBlurDrawable

Aggregator如何连通ViewRootImpl和BackgroundBlurDrawable

每一次刷新界面时,如果Aggregator模糊区域发生更新 或者存在模糊区域

会读取当前的模糊区域参数,发送给SurfaceFlinger端

每个BackgroundBlurDrawable都可以转换成一个BlurRegion数据结构,

所以多个Drawable就转换成了一个BlurRegion数组

一个BlurRegion可以转换为一个float数组,那么多个BlurRegion可转换为一个float二维数组

即 多个BackgroundBlurDrawable记录的模糊参数,最终转换成了float二维数组

然后将表示模糊参数的float二维数组通过setBlurRegions下设

有一个细节是:监听模糊坐标范围mRect更新并没有立即执行,而是作为Runable和帧数一起记下,在getBlurRegionsToDispatchToSf时再真正执行,这样避免了多线程同步问题。

如果mRect立即更新,该操作在线程池中执行,无法保证执行顺序。假如监听到第100帧的RenderNoder位置变化mRect立即更新了,但是renderThread此时正在请求渲染第99帧,却使用了第100帧的位置,就会出现位置错位的问题。

总结

综上,blur behind 本质上是使用了setBackgroundBlurRadius background blur本质上是使用了setBlurRegions

那么利用上面的接口,就可以实现surface的实时模糊显示。

比如:在一个surfaceView中显示视频或者3D画面,上面的surface使用上面的接口就可以实现模糊效果。

相关推荐
Libraeking2 小时前
破壁行动:在旧项目中丝滑嵌入 Compose(混合开发实战)
android·经验分享·android jetpack
市场部需要一个软件开发岗位3 小时前
JAVA开发常见安全问题:Cookie 中明文存储用户名、密码
android·java·安全
JMchen1235 小时前
Android后台服务与网络保活:WorkManager的实战应用
android·java·网络·kotlin·php·android-studio
crmscs5 小时前
剪映永久解锁版/电脑版永久会员VIP/安卓SVIP手机永久版下载
android·智能手机·电脑
localbob5 小时前
杀戮尖塔 v6 MOD整合版(Slay the Spire)安卓+PC端免安装中文版分享 卡牌肉鸽神作!杀戮尖塔中文版,电脑和手机都能玩!杀戮尖塔.exe 杀戮尖塔.apk
android·杀戮尖塔apk·杀戮尖塔exe·游戏分享
机建狂魔5 小时前
手机秒变电影机:Blackmagic Camera + LUT滤镜包的专业级视频解决方案
android·拍照·摄影·lut滤镜·拍摄·摄像·录像
hudawei9965 小时前
flutter和Android动画的对比
android·flutter·动画
lxysbly7 小时前
md模拟器安卓版带金手指2026
android
儿歌八万首8 小时前
硬核春节:用 Compose 打造“赛博鞭炮”
android·kotlin·compose·春节
消失的旧时光-194311 小时前
从 Kotlin 到 Dart:为什么 sealed 是处理「多种返回结果」的最佳方式?
android·开发语言·flutter·架构·kotlin·sealed