Flutter BackdropFilter 实现高斯模糊

栏目: IOS · Android · 发布时间: 4年前

内容简介:现在应该很多地方都会使用到高斯模糊的效果,想当初在Android上实现差点没要了我的老命,那么在 Flutter 中实现会是如何?Flutter 提供了 BackdropFilter 来实现高斯模糊的效果,照例打开源码:可以看到必须要传一个

现在应该很多地方都会使用到高斯模糊的效果,想当初在Android上实现差点没要了我的老命,那么在 Flutter 中实现会是如何?

什么是BackdropFilter,怎么使用

Flutter 提供了 BackdropFilter 来实现高斯模糊的效果,照例打开源码:

class BackdropFilter extends SingleChildRenderObjectWidget {
  /// Creates a backdrop filter.
  ///
  /// The [filter] argument must not be null.
  const BackdropFilter({
    Key key,
    @required this.filter,
    Widget child,
  }) : assert(filter != null),
       super(key: key, child: child);

  /// The image filter to apply to the existing painted content before painting the child.
  ///
  /// For example, consider using [ImageFilter.blur] to create a backdrop
  /// blur effect
  final ui.ImageFilter filter;
}
复制代码

可以看到必须要传一个 ImageFilter filter ,而且注释上也写了

For example, consider using [ImageFilter.blur] to create a backdrop blur effect

例如,考虑使用 ImageFilter.blur 来说创建一个背景模糊的效果。

而且,在类的上面还有很长的一段注释:

/// A widget that applies a filter to the existing painted content and then
/// paints [child].
///
/// The filter will be applied to all the area within its parent or ancestor
/// widget's clip. If there's no clip, the filter will be applied to the full
/// screen.
///
/// {@youtube 560 315 https://www.youtube.com/watch?v=dYRs7Q1vfYI}
///
/// {@tool sample}
/// If the [BackdropFilter] needs to be applied to an area that exactly matches
/// its child, wraps the [BackdropFilter] with a clip widget that clips exactly
/// to that child.
///
/// ```dart
/// Stack(
///   fit: StackFit.expand,
///   children: <Widget>[
///     Text('0' * 10000),
///     Center(
///       child: ClipRect(  // <-- clips to the 200x200 [Container] below
///         child: BackdropFilter(
///           filter: ui.ImageFilter.blur(
///             sigmaX: 5.0,
///             sigmaY: 5.0,
///           ),
///           child: Container(
///             alignment: Alignment.center,
///             width: 200.0,
///             height: 200.0,
///             child: Text('Hello World'),
///           ),
///         ),
///       ),
///     ),
///   ],
/// )
/// ```
复制代码

最前面一段话说的是:如果你不设置他大小的话,这个组件将是全屏的。

然后!他放出来了一个 YouTube 的视频!还有一段Demo

那话不多说,我们直接运行官方给出来的Demo,看看是什么效果:

Flutter BackdropFilter 实现高斯模糊

当这一大串 0 显示在我眼前的时候我差点瞎了。

不过可以看到使用 BackdropFilter 非常简单就实现了高斯模糊的效果。

自定义高斯模糊组件

那我们可以按照Demo的思路来封装几个背景是高斯模糊的控件:

class BlurOvalWidget extends StatelessWidget {
  final Widget _widget;
  double _padding = 10;

  BlurOvalWidget(this._widget, {double padding = 0}) {
    if (padding != 0) this._padding = padding;
  }

  @override
  Widget build(BuildContext context) {
    return ClipOval(
      child: BackdropFilter(
        filter: ImageFilter.blur(
          sigmaX: 10,
          sigmaY: 10,
        ),
        child: Container(
          color: Colors.white10,
          padding: EdgeInsets.all(_padding),
          child: _widget,
        ),
      ),
    );
  }
}
复制代码

我们使用的是无状态的小部件,构造函数里需要传入一个widget,用来放在模糊的背景上面。

然后我们的build 方法直接返回一个圆形的模糊背景,横纵向模糊的数值为10,值越大,模糊的效果就越大。

不能光有圆形的模糊背景,再来一个圆角矩形的:

class BlurRectWidget extends StatelessWidget {
  final Widget _widget;
  double _padding = 10;

  BlurRectWidget(this._widget, {double padding = 0}) {
    if (padding != 0) this._padding = padding;
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 50),
      child: ClipRRect(
        borderRadius: BorderRadius.all(Radius.circular(10)),
        child: BackdropFilter(
          filter: ImageFilter.blur(
            sigmaX: 20,
            sigmaY: 20,
          ),
          child: Container(
            color: Colors.white10,
            padding: EdgeInsets.all(_padding),
            child: _widget,
          ),
        ),
      ),
    );
  }
}
复制代码

代码基本一样,只不过就是把 ClipOval 换成了 ClipRRect

现在我们用封装好的两个 widget 来实现一个比较简单的页面:

Flutter BackdropFilter 实现高斯模糊

上面的文字用到了我们定义的圆角矩形,下面的用到了我们定义的圆形。

代码如下,比较简单,就是普通的搭建页面:

class _BackdropFilterPageState extends State<BackdropFilterPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('BackdropFilterPageState'),
      ),
      body: Stack(
        fit: StackFit.expand,
        children: <Widget>[
          Image.asset(
            'images/bg.jpg',
            fit: BoxFit.cover,
          ),
          Center(
            child: BlurRectWidget(
              Column(
                mainAxisSize: MainAxisSize.min,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  Text(
                    'BackdropFilter class',
                    style: TextStyle(
                      fontSize: 16,
                      color: Colors.white,
                    ),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 5.0),
                    child: Text(
                      'A widget that applies a filter to the existing painted content and then paints child.'
                      'The filter will be applied to all the area within its parent or ancestor widget\'s clip. If there\'s no clip, the filter will be applied to the full screen.',
                      style: TextStyle(fontSize: 14, color: Colors.black87),
                      textAlign: TextAlign.justify,
                    ),
                  ),
                ],
              ),
            ),
          ),
          Container(
            alignment: Alignment.bottomCenter,
            margin: EdgeInsets.only(bottom: 150),
            child: Row(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                BlurOvalWidget(
                  IconButton(
                    onPressed: (){
                      Navigator.of(context).push(MaterialPageRoute(builder: (context){
                        return BlurImagePage();
                      }));
                    },
                    icon: Icon(
                      Icons.favorite,
                      color: Colors.white,
                    ),
                    iconSize: 30,
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 50.0),
                  child: BlurOvalWidget(
                    Icon(
                      Icons.share,
                      color: Colors.white,
                      size: 30,
                    ),
                  ),
                ),
                BlurOvalWidget(
                  Icon(
                    Icons.bookmark,
                    color: Colors.white,
                    size: 30,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}
复制代码

如何把高斯模糊当做前景

那这个时候就有人问了,只能把模糊放在背景里吗,不能用来当前景吗?

当然可以,不然我还费这么多话干什么?

先看一下效果图:

Flutter BackdropFilter 实现高斯模糊

怎么样,是不是你要的感觉:full_moon_with_face:,有没有一种想要充钱的冲动!

当然,这种效果实现起来也是非常的简单,我们只需要把 BackdropFilter 的 child 设置为一个 Container(),并且设置上颜色(我这里使用的是 Colors.white10),然后放在 Stack 中就ok啦。

代码如下:

class BlurImagePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
          alignment: Alignment.center,
          child: Stack(
            alignment: Alignment.center,
            children: <Widget>[
              Container(
                margin: EdgeInsets.symmetric(horizontal: 20),
                child: Image.asset(
                  'images/wanimal.png',
                  fit: BoxFit.cover,
                ),
              ),
              Positioned.fill(
                child: BackdropFilter(
                  filter: ImageFilter.blur(
                    sigmaX: 15,
                    sigmaY: 15,
                  ),
                  child: Container(
                    color: Colors.white10,
                  ),
                ),
              ),
              RaisedButton(
                textColor: Colors.white,
                shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5))),
                color: Colors.orangeAccent,
                child: Text('充钱查看更多', style: TextStyle(fontSize: 16),),
                onPressed: (){},
              )
            ],
          )),
    );
  }
}
复制代码

先放我们需要被遮住的 widget,然后放上我们的模糊 widget,再然后就可以让用户充钱了。

小结

BackdropFilter 不仅仅只可以做高斯模糊的效果,也可以用来做旋转,倾斜等。

只不过我们常用的是高斯模糊,其原理一样。

了解更多可以移步 Flutter 官网:flutter.dev/

原文代码移步Giuhub: github.com/wanglu1209/…

图我就不传了,23333.

Flutter BackdropFilter 实现高斯模糊

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

淘宝十年产品事

淘宝十年产品事

苏杰 / 电子工业出版社 / 2013-10-15 / 55.00

产品经理发展到一定阶段,再要成长,光靠学习一些知识、技能已经不够,必须通过经典案例来学习,而本书,就提供了小到页面细节、大到平台架构的丰富案例。电商从业者,无法无视“淘宝”这个标杆的存在,本书可帮助大家做出更好的选择。愿意思考的人们,也可以从“淘宝”这个产品,或者说社会 现象、经济现象里,找到每天都能体会到的那些变化的原因,从而想得更明白,活得更通透。 本书细数淘宝成立十年来经历的重大变化,......一起来看看 《淘宝十年产品事》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

MD5 加密
MD5 加密

MD5 加密工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具