如何裁剪具有平滑边缘的BackdropFilter?

8

我想在Flutter中对一张图片应用BackdropFilter。所以,我使用了下面在Flutter文档中提供的方式来应用过滤器。

import 'dart:ui';
import 'package:flutter/material.dart';

void main() {
   runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: MyApp(),
      ),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.bottomCenter,
          children: <Widget>[
            Container(
              height: 500,
              child: Image.network('https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQlXYdeEKhFq34sh8-0ZKC1uqCcVGgOzdW_ZRAqCBkWxG-oeCB1'),
            ),
            Positioned(
              top: 300,
              bottom: 0,
              left: 0,
              right: 0,
              child: ClipRect(
                child: BackdropFilter(
                  filter: ImageFilter.blur(sigmaX: 2, sigmaY: 10),
                  child: Container(
                    color: Colors.black.withOpacity(0),
                  ),
                ),
              ),
            ),
          ]
        ),
      ),
    );
  }
}

它产生了以下输出: 我的代码输出 我在BackdropFilter和Image之间得到了一个硬边缘,虽然我想要它们之间的边缘更加平滑。
我该如何实现类似于这样的效果?

1
我进行了一些实验,但即使是Flutter团队YouTube视频中的原始代码也不能像视频中展示的那样工作。 Positioned Widget不像他们展示的那样工作,而对其进行剪裁会给我带来与您得到的相同的结果。 - J. S.
2个回答

9

我能够实现它,但目前没有直接实现的方法。 创建该效果的函数如下: 该函数将接收您想要模糊的小部件列表。

List<Widget> buildBlurredImage(List<Widget> l) {
    List<Widget> list = [];
    list.addAll(l);
    double sigmaX = 0;
    double sigmaY = 0.1;
    for (int i = 100; i < 350; i += 5) {
     // 100 is the starting height of blur
     // 350 is the ending height of blur
      list.add(Positioned(
        top: i.toDouble(),
        bottom: 0,
        left: 0,
        right: 0,
        child: ClipRect(
          child: BackdropFilter(
            filter: ImageFilter.blur(
              sigmaX: sigmaX,
              sigmaY: sigmaY,
            ),
            child: Container(
              color: Colors.black.withOpacity(0),
            ),
          ),
        ),
      ));
      sigmaX += 0.1;
      sigmaY += 0.1;
    }
    return list;
  }

然后在您的小部件类内部,使用以下方式使用该函数

@override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.bottomCenter,
          // children: <Widget>[],
          children: buildBlurredImage([
            Container(
              height: 500,
              child: Image.network(
                'https://www.thewowstyle.com/wp-content/uploads/2015/02/Beautiful-Wallpapers-14.jpg',
                fit: BoxFit.cover,
              ),
            ),
          ]),
        ),
      ),
    );
  }

enter image description here

你的最终小部件类将看起来像这样

class MyApp extends StatelessWidget {
  List<Widget> buildBlurredImage(List<Widget> l) {
    List<Widget> list = [];
    list.addAll(l);
    double sigmaX = 0;
    double sigmaY = 0.1;
    for (int i = 100; i < 350; i += 5) {
      // 100 is the starting height of blur
      // 350 is the ending height of blur
      list.add(Positioned(
        top: i.toDouble(),
        bottom: 0,
        left: 0,
        right: 0,
        child: ClipRect(
          child: BackdropFilter(
            filter: ImageFilter.blur(
              sigmaX: sigmaX,
              sigmaY: sigmaY,
            ),
            child: Container(
              color: Colors.black.withOpacity(0),
            ),
          ),
        ),
      ));
      sigmaX += 0.1;
      sigmaY += 0.1;
    }
    return list;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Stack(
          alignment: Alignment.bottomCenter,
          // children: <Widget>[],
          children: buildBlurredImage([
            Container(
              height: 500,
              child: Image.network(
                'https://www.thewowstyle.com/wp-content/uploads/2015/02/Beautiful-Wallpapers-14.jpg',
                fit: BoxFit.cover,
              ),
            ),
          ]),
        ),
      ),
    );
  }
}

3
我认为最好的方法是在BackdropFilter上使用ShaderMask。
不幸的是,由于引擎的更改,这种方法已经失效:链接
我在Flutter上创建了一个问题问题,希望他们能尽快解决这个问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接