Flutter 53: 图解 BackdropFilter 高斯模糊

      小菜在学习时想要做一点类似毛玻璃的效果,首先想到的是高斯模糊,对于原生 Android 需要话费很多精力,而 Flutter 提供了 BackdropFilter 高斯模糊的 Widget,真的很方便;

源码分析

const BackdropFilter({
    Key key,
    @required this.filter,
    Widget child
})

      分析源码,必须要传递 filter 参数,用来构建模糊层效果;小菜理解只是通过 BackdropFilter 构建一个模糊图层,借助 Stack 等设置图层是在上层或下层,官方也推荐了 DecoratedBox 设置图层上下;

      模糊图层通常借用 ImageFilter.blur 设置模糊度,一般是在 0.0-10.0 之间,数值越大模糊度越高,超过 10.0 时完全不可见;

      小菜在设置模糊颜色时尝试了 withOpacity 方法,一般是在 0.0-1.0 之间,用来设置颜色值的透明度;也可以采用 withAlpha 方法,效果相同,一般是在 0-255 之间;同时还可以采用 withRed / withGreen / withBlue 直接设置三原色的基础值实现不同效果;

Widget _imageBackWid() {
  return Center(
      child: Column(mainAxisSize: MainAxisSize.min, children: <Widget>[
    Row(children: <Widget>[
      _itemWid(Colors.red.withOpacity(0.1), 4.0),
      _itemWid(Colors.white.withOpacity(0.1), 8.0),
    ]),
    Row(children: <Widget>[
      _itemWid(Colors.white.withOpacity(0.1), 4.0),
      Container(
          width: MediaQuery.of(context).size.width * 0.5,
          height: MediaQuery.of(context).size.width * 0.5,
          child: BackdropFilter(
              filter: ImageFilter.blur(sigmaX: 4.0, sigmaY: 4.0),
              child: Container(
                  color: Colors.white.withOpacity(0.1),
                  child: Padding(
                      padding: EdgeInsets.all(14.0),
                      child: Image.asset('images/icon_hzw01.jpg')))))
    ])
  ]));
}

Widget _itemWid(color, blur) {
  return Container(
      width: MediaQuery.of(context).size.width * 0.5,
      height: MediaQuery.of(context).size.width * 0.5,
      child: Stack(children: <Widget>[
        Padding(
            padding: EdgeInsets.all(14.0),
            child: Image.asset('images/icon_hzw01.jpg')),
        BackdropFilter(
            filter: ImageFilter.blur(sigmaX: blur, sigmaY: blur),
            child: Container(color: color))
      ]));
}

      小菜尝试了一个很不完善的小案例,类似于查看截图的小窗口,遮罩层是模糊图层;小菜用了很蠢的方式来处理,底部是一个设置了高斯模糊的背景图,上层通过 Canvas 展示一张完全相同的图片,借用 drawImage 实现小窗口,再通过手指坐标控制窗口位置;未对机型适配,仅作为一个不完善的小测试案例;

      小菜附上核心代码仅供参考,若有更好的方法请多多指导!

class BackDropCanvas extends CustomPainter {
  ui.Image background;
  BuildContext context;
  var dx = 0.0, dy = 0.0;
  static const double smallScan = 200.0;
  BackDropCanvas(this.context, this.background, this.dx, this.dy);

  @override
  void paint(Canvas canvas, Size size) {
    canvas.clipPath(Path()
      ..moveTo((Screen.width - smallScan) * 0.5 + dx,
          (Screen.height - smallScan) * 0.5 + dy)
      ..lineTo((Screen.width + smallScan) * 0.5 + dx,
          (Screen.height - smallScan) * 0.5 + dy)
      ..lineTo((Screen.width + smallScan) * 0.5 + dx,
          (Screen.height + smallScan) * 0.5 + dy)
      ..lineTo((Screen.width - smallScan) * 0.5 + dx,
          (Screen.height + smallScan) * 0.5 + dy));
    canvas.drawImage(this.background, ui.Offset.zero, Paint());
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

class _BackedDropPage extends State<BackedDropPage> {
  ui.Image _background;
  bool _prepDone;
  var dx = 0.0, dy = 0.0;
  static const double smallScan = 200.0;

  @override
  void initState() {
    _prepDone = false;
    super.initState();
    _prepare();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Stack(children: <Widget>[
      Container(
          width: Screen.width,
          height: Screen.height,
          child: Stack(children: <Widget>[
            Center(child: Image.asset('images/icon_hzw04_1.jpg')),
            BackdropFilter(
                filter: ImageFilter.blur(sigmaX: 4.0, sigmaY: 4.0),
                child: Container(color: Colors.black.withOpacity(0.2)))
          ])),
      _prepDone
          ? Container(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              child: CustomPaint(
                  painter: BackDropCanvas(context, _background, dx, dy)))
          : Container(color: Colors.grey),
      GestureDetector(onPanUpdate: (d) {
        if (d.globalPosition.dx >= smallScan * 0.5 &&
            d.globalPosition.dx <= Screen.width - smallScan * 0.5) {
          dx = d.globalPosition.dx - Screen.width * 0.5;
        }
        if (d.globalPosition.dy >= smallScan * 0.5 &&
            d.globalPosition.dy <= Screen.height - smallScan * 0.5) {
          dy = d.globalPosition.dy - Screen.height * 0.5;
        }
        setState(() {});
      })
    ]));
  }

  _prepare() {
    loadImage('images/icon_hzw04_1.jpg').then((image) {
      _background = image;
    }).whenComplete(() {
      _prepDone = true;
      setState(() {});
    });
  }
}

      BackdropFilter 高斯模糊是一个实用且方便的 Widget,可灵活应用在项目中;小菜对此研究还不够深入,有问题的话请多多指导!

来源:阿策小和尚

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266

推荐阅读更多精彩内容