我一直在try 通过自己创建一个新的RenderObject来对堆栈中的子元素使用图像滤镜模糊.由于某些原因,我必须使用renderObject,所以我不能使用预构建的(Backdrop filter和ClipPath)小部件.

以下是代码:

import 'dart:ui';

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter image filter blur demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const Demo(),
    );
  }
}

class Demo extends StatefulWidget {
  const Demo({super.key});

  @override
  State<Demo> createState() => _DemoState();
}

class _DemoState extends State<Demo> {
  Offset offset = Offset.zero;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          // if i comment this it will clip the element
          const Text("hello welcome to the demo of the backdrop blur"),
          Positioned(
            top: offset.dy,
            left: offset.dx,
            child: GestureDetector(
              onPanUpdate: (d) {
                setState(() {
                  offset += d.delta;
                });
              },
              child: SizedBox(
                width: 100,
                height: 100,
                child: Blur(
                    child: Container(
                  width: 100,
                  height: 100,
                  color: Colors.red.withOpacity(0.3),
                )),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class Blur extends SingleChildRenderObjectWidget {
  const Blur({
    Key? key,
    Widget? child,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderBlur();
  }

  @override
  void updateRenderObject(
      BuildContext context, RenderBlur renderObject) {}
}

class RenderBlur extends RenderProxyBox {
  @override
  void paint(PaintingContext context, Offset offset) {
      //paint child
    context.paintChild(child!, offset);

    final blurLayer = BackdropFilterLayer(
      filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
      blendMode: BlendMode.srcOver,
    );
    final clipLayer = ClipPathLayer(
      clipPath: Path()..addRect(offset & size),
    );

    context.addLayer(blurLayer);
    context.addLayer(clipLayer);

    // needs to `Path`

    super.paint(context, offset);
  }
}


result:enter image description here

通过对堆栈的第一个子级进行注释,它可以正常工作:

enter image description here

推荐答案

好的,所以问题是:

  1. 在这种情况下,Stack实际上并没有填满屏幕.它适合它的子元素们的尺寸,在这种情况下是Text号.你会想把它包在SizedBox()或其他什么东西里,这样它就会填满屏幕.
  2. 您希望模糊背景,但仅限于边界内.所以,你要做的就是在剪贴层的画笔里添加模糊层.

所以我认为你想要做的是:

Corrected Screenshot

import 'dart:ui' as ui;

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter image filter blur demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const Demo(),
    );
  }
}

class Demo extends StatefulWidget {
  const Demo({super.key});

  @override
  State<Demo> createState() => _DemoState();
}

class _DemoState extends State<Demo> {
  Offset offset = Offset.zero;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SizedBox(
        width: double.infinity,
        height: double.infinity,
        child: Stack(
          children: [
            const Text("hello welcome to the demo of the backdrop blur"),
            Transform.translate(
              offset: offset,
              child: GestureDetector(
                onPanUpdate: (d) {
                  setState(() {
                    offset += d.delta;
                  });
                },
                child: Blur(
                  child: Container(
                    width: 100,
                    height: 100,
                    color: Colors.red.withOpacity(0.3),
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class Blur extends SingleChildRenderObjectWidget {
  const Blur({
    Key? key,
    Widget? child,
  }) : super(key: key, child: child);

  @override
  RenderObject createRenderObject(BuildContext context) {
    return RenderBlur();
  }

  @override
  void updateRenderObject(BuildContext context, RenderBlur renderObject) {}
}

class RenderBlur extends RenderProxyBox {
  @override
  void paint(PaintingContext context, Offset offset) {
    final blurLayer = BackdropFilterLayer(
      filter: ui.ImageFilter.blur(sigmaX: 5, sigmaY: 5),
      blendMode: BlendMode.srcOver,
    );
    final clipLayer = ClipPathLayer(
      clipPath: Path()..addRect(offset & size),
    );
    context.pushLayer(clipLayer, (context, offset) {
      context.addLayer(blurLayer);
      super.paint(context, offset); // This probably shouldn't be here, I don't know what you wanted so just try and move it around.
    }, offset);
  }
}

Flutter相关问答推荐

当仅点击一行时,所有行都被选中

为什么当我使用Riverpod更新状态时,列表会被刷新?

升级到Ffltter 3.16后,应用程序栏、背景 colored颜色 、按钮大小和间距都会发生变化

Android工作室Flutter 热重新加载更新后不工作

Flutter Dismissible 不会在 startToEnd 滑动时被关闭

Flutter如何从深入嵌套的小部件中打开抽屉?

Flutter底部面板局部显示

Flutter蓝牙 - 如何通过蓝牙从设备中获取文件?

Flutter 判断 Uint8List 是否有效 Image

Flutter:如何在 bottomsheet 中创建一个日期 Select 器,如下图所示

Elevated 和 Outlined 按钮之间的动画

如何在向下滚动时隐藏顶部卡片并在向上滚动时出现?

Show Snackbar above to showModalBottomSheet Flutter

Flutter中如何连续获取TextField的文本是否为空?

statefulWidget 无法进行所需更改的问题

type '({bool growable}) => List' 不是类型转换中类型 'List' 的子类型

如何在 flutter 中制作这种类型的扩展瓦片

Banner Ad.test 广告单元 ID 是否已过时?

我可以使用 Future 来填充Text() 小部件而不是在 Flutter 中使用 FutureBuilder 吗?

如何在Flutter 中专注于列表视图中最新添加的项目