Flutter 实现 Glassmorphic 高斯模糊效果
视频
前言
参考
https://api.flutter.dev/flutter/painting/LinearGradient-class.html
https://api.flutter.dev/flutter/painting/BoxDecoration-class.html
https://api.flutter.dev/flutter/painting/LinearGradient-class.html
正文
我们写了 4 个类:
ColorBackground
. 只是一个具有颜色和不透明度的容器。GradientBackground
. 带有渐变、不透明度和模糊的容器。ImageBackground
. 包含图像、不透明度和模糊效果的容器。TranslucentPanel
.
前三个旨在用作背景,并且可以将它们组合使用。创建这些自定义小部件的主要目的是使视图的代码更简单和简洁。
这里有一些例子:
在左边,我放置了 GradientBackground,其不透明度为 1.0,并在其上放置了 ColorBackground。在右边——相反。
有一件事情对我来说很有趣,就是是否先放什么东西会有区别。结果显示并没有。我们可以通过调整顶部背景的不透明度来获得几乎相同的结果。
以下是 Golor over Gradient 示例的全部代码:
class ColorOverGradientView extends GetView<ColorOverGradientController> {
const ColorOverGradientView({super.key});
@override
Widget build(BuildContext context) {
return GradientBackground(
colors: [Colors.purple, Colors.black, Colors.red, Colors.blue],
child: ColorBackground(
color: Colors.lightBlueAccent,
opacity: 0.4,
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
leading: CupertinoButton(
child: Icon(Icons.chevron_left, color: Colors.white, size: 30,),
onPressed: () {
Get.back();
}),
backgroundColor: Colors.transparent,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TranslucentPanel(
width: 300,
height: 100,
child: Center(
child: Text(
'Color Over Gradient',
style: TextStyle(fontSize: 30, color: Colors.white70),
),
),
),
],
),
),
),
),
);
}
}
图像上的颜色:
在右侧,我添加了一些模糊效果。
以下是所有三个背景和半透明面板的代码:
color_background.dart
import 'package:flutter/material.dart';
import 'package:getx_glassmorphic_no_package/app/modules/ui_extensions.dart';
final class ColorBackground extends StatelessWidget {
final double width;
final double height;
final Color color;
final double opacity;
final Widget? child;
const ColorBackground(
{super.key,
this.width = double.infinity,
this.height = double.infinity,
required this.color,
this.opacity = 1,
this.child});
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
color: color.withOpacityExt(opacity),
child: child,
);
}
}
唯一必需的参数是 color
。
gradient_background.dart
import 'dart:ui';
import 'package:flutter/material.dart';
final class GradientBackground extends StatelessWidget {
final double width;
final double height;
final List<Color> colors;
final double opacity;
final Widget? child;
final GradientType gradientType; //circular, linear, sweep
final Gradient? gradient;
final double blur;
const GradientBackground({
super.key,
this.width = double.infinity,
this.height = double.infinity,
required this.colors,
this.opacity = 1.0,
this.child,
this.gradientType = GradientType.linear,
this.gradient,
this.blur = 0,
});
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
decoration: BoxDecoration(
gradient: gradient ?? _createGradient(colors, opacity, gradientType),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
child: child,
),
);
}
Gradient _createGradient(
List<Color> colors,
double opacity,
GradientType gradientType,
) {
switch (gradientType) {
case GradientType.radial:
return RadialGradient(colors: colors).withOpacity(opacity);
case GradientType.sweep:
return SweepGradient(colors: colors).withOpacity(opacity);
default:
return LinearGradient(
colors: colors,
begin: Alignment.topLeft,
end: Alignment.bottomRight)
.withOpacity(opacity);
}
}
}
enum GradientType { linear, radial, sweep }
唯一必需的参数是 colors
( List<Color>
)。
image_background.dart
import 'dart:ui';
import 'package:flutter/material.dart';
final class ImageBackground extends StatelessWidget {
final double width;
final double height;
final ImageProvider<Object> image;
final double opacity;
final Widget? child;
final double blur;
const ImageBackground(
{super.key,
this.width = double.infinity,
this.height = double.infinity,
required this.image,
this.opacity = 1,
this.blur = 0,
this.child});
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
decoration: BoxDecoration(
image: DecorationImage(
image: image,
fit: BoxFit.cover,
opacity: opacity,
),
),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
child: child,
),
);
}
}
唯一必需的参数是 image
。
translucent_panel.dart
import 'package:flutter/material.dart';
import 'package:getx_glassmorphic_no_package/app/modules/ui_extensions.dart';
final class TranslucentPanel extends StatelessWidget {
final double width;
final double height;
final double borderRadius;
final Widget? child;
const TranslucentPanel(
{super.key,
this.width = double.infinity,
this.height = double.infinity,
this.borderRadius = 12,
this.child});
@override
Widget build(BuildContext context) {
return Container(
width: width,
height: height,
decoration: BoxDecoration(
gradient: LinearGradient(colors: [
Colors.white,
Colors.white.withOpacityExt(0.9),
Colors.white,
Colors.white.withOpacityExt(0.9),
]).withOpacity(0.15),
border: Border.all(
color: Colors.white,
width: 0.5,
),
borderRadius: BorderRadius.all(Radius.circular(borderRadius)),
),
child: child,
);
}
}
TranslucentPanel
没有必需的参数,但在大多数情况下,我们应该指定 width
和 height
。否则,它将占据整个屏幕。
好的,最后一个例子是 Gradient over Image。
从左到右:线性、径向和扫掠渐变。线性,依我之见,完美地融合到了图像中。
这里是线性代码:
class GradientOverImageView extends GetView<GradientOverImageController> {
const GradientOverImageView({super.key});
@override
Widget build(BuildContext context) {
return ImageBackground(
image: NetworkImage(
'https://images.unsplash.com/photo-1460627390041-532a28402358?q=80&w=1470&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'),
child: GradientBackground(
gradientType: GradientType.linear,
opacity: 0.6,
colors: [Colors.purple, Colors.black, Colors.red, Colors.blue],
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
leading: CupertinoButton(
child: Icon(Icons.chevron_left, color: Colors.white, size: 30,),
onPressed: () {
Get.back();
}),
backgroundColor: Colors.transparent,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TranslucentPanel(
width: 300,
height: 100,
child: Center(
child: Text(
'Gradient Over Image',
style: TextStyle(fontSize: 30, color: Colors.white70),
),
),
),
],
),
),
),
),
);
}
}
要将其更改为径向或扫掠,我们只需相应地更改 gradientType
参数。
小结
本文详细介绍了如何在 Flutter 中实现玻璃模糊效果,包括代码示例和设计技巧,帮助开发者提升应用的视觉效果。
感谢阅读本文
如果有什么建议,请在评论中让我知道。我很乐意改进。
猫哥 APP
flutter 学习路径
- Flutter 优秀插件推荐
- Flutter 基础篇1 - Dart 语言学习
- Flutter 基础篇2 - 快速上手
- Flutter 实战1 - Getx Woo 电商APP
- Flutter 实战2 - 上架指南 Apple Store、Google Play
- Flutter 基础篇3 - 仿微信朋友圈
- Flutter 实战3 - 腾讯即时通讯 第一篇
- Flutter 实战4 - 腾讯即时通讯 第二篇
© 猫哥 ducafecat.com
end