Windows 10 应用创建模糊背景窗口的三种方法

本文介绍在Windows10上创建模糊背景窗口的三种方法:调用Win32API SetWindowCompositionAttribute,使用WPF BlurEffect,及UWP AcrylicBrush。每种方法各有优劣,适用于不同场景。

原文 Windows 10 应用创建模糊背景窗口的三种方法

现代的操作系统中创建一张图片的高斯模糊效果非常容易,不过如果要在窗口中获得模糊支持就需要操作系统的原生支持了。iOS/Mac 和 Windows 系统都对此有支持。

本文将介绍三种创建模糊背景窗口的方法。有人可能喜欢称之为毛玻璃窗口、亚克力窗口。


This post is written in multiple languages. Please select yours:

 

最早我是在 StackOverflow 上回答一位网友的提问时写了一份非常长的答案,后来小伙伴建议我将答案改写成博客,于是我就改了。StackOverflow 上的答案在这里:colors - WPF: How to Style my form with Transparency levels - Stack Overflow

三种创建模糊背景窗口的方法

Windows 10 上创建带模糊背景的窗口有三种不同的方法,不过每一种都是既有好处又有坏处的:

  1. 调用 Win32 API —— SetWindowCompositionAttribute,使用这种方式能够获得一个背景轻微透明的窗口。当然,如果需要模拟亚克力效果或者是 iOS/Mac 上的模糊效果就 gg 了。
    The image from my post

  2. 为窗口中的背景图片添加 WPF 自带的模糊效果 BlurEffect。这种方式你想获得多大的模糊半径就能获得多大的模糊半径,不过带来的就是更高的性能损耗。同时,还得考虑在移动窗口的时候动态地去更新背景图片并再次模糊。
    BlurEffect of WPF

  3. 使用 Fluent Design System 中的亚克力效果 —— AcrylicBrush。这绝对是 Windows 10 上获得背景模糊效果中视觉效果最好,同时又最省性能的方法了。不过,这种方法只能在 UWP 应用中使用。
    The UWP AcrylicBrush from docs.microsoft.com


SetWindowCompositionAttribute API

SetWindowCompositionAttribute 并没有那么好调用,所以我为此写了一个辅助类类封装对背景模糊效果的调用。使用这个辅助类,你只需要使用一行代码就能开启背景模糊效果。

可以在 XAML 代码中使用 interop:WindowBlur.IsEnabled="True"

<Window x:Class="Walterlv.Demo.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:interop="clr-namespace:Walterlv.Demo.Interop" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525" interop:WindowBlur.IsEnabled="True" Background="Transparent"> </Window> 

可以在 cs 代码中使用 WindowBlur.SetIsEnabled(this, true)

public class MainWindow : Window { public MainWindow() { InitializeComponent(); WindowBlur.SetIsEnabled(this, true); } } 

我为 WindowBlur 类准备了一个 GitHub Gist,在这里:https://gist.github.com/walterlv/752669f389978440d344941a5fcd5b00。你只需要将代码全部复制到你的项目中即可开始使用。

当然,我还写了一篇博客专门讲使用 SetWindowCompositionAttribute API 实现背景模糊效果:在 Windows 10 上为 WPF 窗口添加模糊特效(就像开始菜单和操作中心那样)

WPF BlurEffect

WPF 的 UIElement 都有 Effect 属性,将其设置为 BlurEffect 即可获得控件的高斯模糊效果。

<Window x:Class="MejirdrituTeWarqoudear.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" AllowsTransparency="True" WindowStyle="None" Width="540" Height="360"> <Grid> <Image Source="YourImageFile.jpg" Stretch="Fill" Margin="-60"> <Image.Effect> <BlurEffect KernelType="Gaussian" Radius="60" /> </Image.Effect> </Image> <Border CornerRadius="60" Margin="30" Background="#7F000000"> <TextBlock Foreground="White" FontSize="20" FontWeight="Light" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"> <Run Text="Hello World" FontSize="48"/> <LineBreak/> <Run Text="walterlv.github.io"/> </TextBlock> </Border> </Grid> </Window> 

特别注意:此方法有严重地性能问题

如果你的窗口是一个异形窗口,例如是具有圆角的矩形,那么你需要额外为控件设置 RectangleGeometry 来裁剪控件。

Rounded Rectangle

<Window x:Class="MejirdrituTeWarqoudear.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="540" Height="360"> <Grid> <Grid.Clip> <RectangleGeometry RadiusX="60" RadiusY="60" Rect="30 30 480 300" /> </Grid.Clip> <Image Source="High+Sierra.jpg" Stretch="Fill" Margin="-60"> <Image.Effect> <BlurEffect KernelType="Gaussian" Radius="60" /> </Image.Effect> </Image> <Border Background="#7F000000"> <TextBlock Foreground="White" FontSize="20" FontWeight="Light" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center"> <Run Text="Hello World" FontSize="48"/> <LineBreak/> <Run Text="walterlv.github.io"/> </TextBlock> </Border> </Grid> </Window> 

如果是圆形窗口,我另外写了一篇文章来说明进行圆形裁剪:WPF 中使用附加属性,将任意 UI 元素或控件裁剪成圆形(椭圆)

UWP AcyclicBrush

微软的官方文档 Acrylic material - UWP app developer - Microsoft Docs 讲解了如何使用亚克力效果。

本文会经常更新,请阅读原文: https://walterlv.com/post/create-blur-background-window.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。 

<think>我们参考了多个引用资料,特别是引用[1]、[2]、[3]、[4]中关于背景模糊效果的实现方法。根据这些引用,我们可以总结出在不同平台和技术中实现浮动窗口背景模糊效果的方法。 引用[1]提到,Android12的窗口模糊处理功能可以跨窗口使用,但非常耗费资源。它对于对话框、底部动作条等浮动窗口非常有用。 引用[2]介绍了一个跨平台(iOS和Android)的模糊处理库,它提供了丰富的配置选项(如blurType, blurAmount等),并强调了性能优化和易用性。 引用[3]则介绍了electron-vibrancy,用于在桌面应用(macOS和Windows)中实现窗口模糊特效。 引用[4]详细描述了在Android抽屉菜单滑动时实现毛玻璃效果的方法:通过预先准备好原图和模糊后的图片,然后根据抽屉菜单露出的高度裁剪模糊图片并设置为背景。 根据用户的问题“我想实现浮动窗口背景模糊效果”,我们需要区分平台: 1. 对于Android平台: - 方法1(系统级):如果设备运行的是Android 12或更高版本,可以使用系统提供的窗口模糊处理功能(如引用[1]所述)。 - 方法2(自定义):如引用[4]所述,预先对背景进行高斯模糊处理,得到一张模糊图片,然后根据浮动窗口的位置和大小,从模糊图片中裁剪相应区域作为浮动窗口背景。这种方法需要实时计算裁剪区域,但可以兼容较低版本的Android。 2. 对于iOS平台: - 可以使用引用[2]中提到的库,它用Objective-C编写原生代码来处理复杂的UI特效,提供了丰富的属性配置。 3. 对于跨平台移动应用(如React Native): - 使用引用[2]中提到的BlurView库,它通过桥接方式实现了高效而美观的模糊计算。 4. 对于桌面应用(如Electron): - 使用引用[3]提到的electron-vibrancy库,它支持macOS和Windows,通过原生实现保证了流畅的用户体验。 5. 对于Web前端: - 可以使用CSS的backdrop-filter属性(注意兼容性)来实现背景模糊效果。例如: ```css .floating-window { backdrop-filter: blur(5px); } ``` 或者,如果考虑兼容性,也可以采用类似引用[4]的方法:使用JavaScript计算背景,然后对背景图片进行模糊处理,再将模糊后的图片作为浮动窗口背景。 具体实现步骤(以Android自定义方法为例,参考引用[4]): 1. 准备两张图片:原图(清晰)和一张经过高斯模糊处理的图片(模糊图)。 2. 在浮动窗口(如抽屉菜单)滑动时,实时获取其露出的高度(或区域)。 3. 根据露出的高度,在模糊图上裁剪对应区域(从模糊图的底部开始裁剪,因为抽屉通常从底部或侧边滑出,且背景图通常与主界面一致)。 4. 将裁剪得到的图片设置为浮动窗口背景。 注意事项: - 性能:模糊处理是计算密集型操作,应避免在每一帧都进行实时模糊,推荐使用预模糊的图片。 - 内存:处理大图时要注意内存占用,及时回收不再使用的Bitmap。 示例代码(Android,使用自定义View实现): ```java public class BlurDrawerLayout extends DrawerLayout { private Bitmap originalBitmap; // 原图 private Bitmap blurredBitmap; // 模糊后的图 private ImageView backgroundView; // 用于显示模糊背景的ImageView public BlurDrawerLayout(Context context) { super(context); init(); } private void init() { // 1. 获取背景图(这里假设背景图是固定的,可以从资源中获取或截屏) // 注意:实际应用中可能需要动态获取当前屏幕的截图 originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.background); // 2. 对原图进行高斯模糊(这里使用RenderScript或第三方库如Glide等实现模糊) blurredBitmap = blurBitmap(originalBitmap); // 3. 创建一个ImageView作为背景 backgroundView = new ImageView(getContext()); backgroundView.setScaleType(ImageView.ScaleType.CROP); // 根据需求设置缩放类型 addView(backgroundView, 0); // 将背景View添加到最底层 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 在滑动过程中,根据抽屉的位置更新背景 } // 假设我们有一个滑动监听器 public void setOnTranslatingListener() { setDrawerListener(new DrawerListener() { @Override public void onDrawerSlide(@NonNull View drawerView, float slideOffset) { // 根据抽屉滑动的距离(或比例)计算需要裁剪的高度 int height = (int) (getHeight() * slideOffset); if (height > 0) { // 裁剪模糊图片的底部区域(假设抽屉从底部滑出) Bitmap clipBitmap = Bitmap.createBitmap(blurredBitmap, 0, blurredBitmap.getHeight() - height, blurredBitmap.getWidth(), height); backgroundView.setImageBitmap(clipBitmap); } } // ... 其他回调方法 }); } // 使用RenderScript进行高斯模糊(示例) private Bitmap blurBitmap(Bitmap original) { // 实现高斯模糊,这里省略具体代码,可以使用RenderScript或第三方库 // 注意:RenderScript在API 17以上支持,低版本需考虑其他方法 return blurred; // 返回模糊后的Bitmap } } ``` 注意:上述代码仅为示例,实际应用中需要考虑更多细节,如截屏获取当前界面、模糊处理的性能优化等。 对于其他平台,请参考相应的库或系统API。 总结:实现浮动窗口背景模糊效果,关键是根据目标平台选择合适的方法,并注意性能优化。</think>### 浮动窗口背景模糊效果实现方法 根据引用资料,实现浮动窗口背景模糊效果主要有以下技术方案,按平台分类: #### 1. **Android 原生实现** **方法一:系统级窗口模糊(Android 12+)** ```java // 启用窗口模糊(需Android 12+) getWindow().setBackgroundBlurRadius(20); // 设置模糊半径 ``` - **优势**:系统原生支持,跨窗口生效(引用[1]) - **限制**:高资源消耗,仅支持 Android 12 及以上版本(引用[1]) **方法二:自定义毛玻璃效果(兼容方案)** ```java // 原理:裁剪预模糊的图片作为背景(引用[4]) @Override public void onTranslating(int gravity, float translation, float fraction) { // 1. 准备两张图:原图 + 高斯模糊后的图片 // 2. 根据抽屉打开高度裁剪模糊图 int height = Math.round(translation); Bitmap clipBitmap = Bitmap.createBitmap( blurBitmap, // 预模糊的位图 0, blurBitmap.getHeight() - height, blurBitmap.getWidth(), height ); drawerBackground.setImageBitmap(clipBitmap); } ``` - **关键点**: - 预生成模糊背景图(通过`RenderScript`或第三方库) - 实时计算浮动窗口露出区域并裁剪对应模糊图 - **适用场景**:抽屉菜单、底部动作条(引用[4]) #### 2. **跨平台方案(React Native)** ```jsx import { BlurView } from "@react-native-community/blurview"; <BlurView blurType="light" // 模糊类型(dark/light/xlight) blurAmount={10} // 模糊强度(0-100) reducedTransparencyFallbackColor="white" > <FloatingWindowContent /> </BlurView> ``` - **特点**(引用[2]): - 原生性能优化(iOS用Objective-C,Android用BlurView库) - 支持动态调节模糊强度 - 自动处理无障碍模式 - **应用场景**:登录页背景、弹出菜单、加载状态层 #### 3. **桌面端(Electron)** ```javascript const { Vibrancy } = require('electron-vibrancy'); Vibrancy.SetViewEffect(window, "acrylic"); // 亚克力模糊效果 // 指定模糊区域 Vibrancy.UpdateViewBounds(window, { x: 0, y: 50, width: 300, height: 200 }); ``` - **特性**(引用[3]): - 支持 macOS/Windows 10+ - 区域局部模糊控制 - 原生级性能(资源占用低) #### 4. **Web前端方案** ```css /* CSS 毛玻璃效果 */ .floating-window { backdrop-filter: blur(10px); /* 关键属性 */ background: rgba(255, 255, 255, 0.5); } ``` - **注意**: - 需处理浏览器兼容性(Safari需`-webkit-backdrop-filter`) - 避免过度使用(性能敏感场景) --- ### 性能优化建议 1. **移动端**: - 预渲染模糊图,避免实时计算(引用[4]) - 限制模糊半径(Android建议<25px,iOS建议<30) 2. **桌面端**: - 使用`electron-vibrancy`指定精确模糊区域(引用[3]) 3. **通用**: - 动态禁用模糊:滚动/动画时暂停效果 - 降级方案:半透明背景(当模糊不可用时) > 示例场景:音乐播放器浮动控件模糊背景(引用[3]) > ![效果示意](https://example.com/blur-demo.gif) > *模糊背景突出前景控件,增强视觉层次感* --- ### 相关问题 1. 如何检测设备是否支持系统级背景模糊? 2. Android 上实现高斯模糊有哪些高效方案? 3. CSS `backdrop-filter` 的浏览器兼容性如何解决? 4. 模糊效果在暗黑模式下需要注意什么视觉设计细节? 5. React Native 的 BlurView 在 Android 低端设备如何优化性能? [^1]: Android 12 窗口模糊特性说明 [^2]: React Native 跨平台模糊实现方案 [^3]: Electron 窗口模糊技术细节 [^4]: Android 抽屉菜单模糊实现原理 [^5]: CSS 浮动布局基础
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值