如何在 flutter canvas 中渲染按钮?

How to render buttons inside flutter canvas?

提问人:JonathanLauxenRomano 提问时间:10/23/2023 更新时间:10/23/2023 访问量:41

问:

我正在一个 flutter draw 项目中工作,需要实现调整最后一个路径大小的功能。但是当我更改列表中的某些项目时,听众坏了!我不知道我做错了什么!我有问题的代码是:

    [...]
      Widget buildCurrentPath(BuildContext context) {
        ValueNotifier<DrawingFunction> activeFunction =
            ValueNotifier(DrawingFunction.draw);
    
        return Listener(
          onPointerDown: (details) {
            final box = context.findRenderObject() as RenderBox;
            final offset = box.globalToLocal(details.position);
    
            if (allSketches.value.isNotEmpty) {
              Rect scaleButtonPosition =
                  allSketches.value.last.getScaleButtonPosition();
    
              if (scaleButtonPosition.contains(offset)) {
                print("Scale button pressed");
                activeFunction.value = DrawingFunction.scale;
              }
            }
            if (activeFunction.value == DrawingFunction.draw) {
              currentSketch.value = Sketch.fromDrawingMode(
                Sketch(
                  points: [offset],
                  color: selectedColor.value,
                  size: strokeSize.value,
                ),
                drawingMode.value,
                filled.value,
              );
            }
          },
          onPointerMove: (details) {
            final box = context.findRenderObject() as RenderBox;
            final offset = box.globalToLocal(details.position);
    
            print(activeFunction);
    
            if (activeFunction.value == DrawingFunction.draw) {
              final points = List<Offset>.from(currentSketch.value?.points ?? [])
                ..add(offset);
    
              currentSketch.value = Sketch.fromDrawingMode(
                Sketch(
                    points: points,
                    color: selectedColor.value,
                    size: strokeSize.value),
                drawingMode.value,
                filled.value,
              );
            } else if (activeFunction.value == DrawingFunction.scale) {
              double scale = 0.9;
    
              Sketch sketch = allSketches.value.last;
              Path transformedPath = sketch.path
                  .transform(Matrix4.diagonal3Values(scale, scale, 1).storage);
    
              sketch.path = transformedPath;
              //currentSketch.value = sketch;
            }
          },
          onPointerUp: (details) {
            if (activeFunction.value == DrawingFunction.draw) {
              allSketches.value = List<Sketch>.from(allSketches.value)
                ..add(currentSketch.value!);
    
              currentSketch.value = null;
            }
          },
          child: RepaintBoundary(
    [...]

在此示例中,对更新进行了注释:当您单击呈现的按钮并移动指针时,drawingFuncions 会保持缩放功能,但是如果我取消注释此行,则指针向下会将 drawingFuncion 更改为 .scale,但 onPointerMove 破坏了这一点,并且 drawingFuncion 又回到了绘制。//currentSketch.value = sketch;

我需要做什么?Flutter canvas 的相同技巧?

颤振 飞镖 绘图

评论


答:

-2赞 kishan viradiya 10/23/2023 #1

要在 Flutter 画布中渲染按钮,您需要在 CustomPainter widget 中使用自定义绘画并手动处理按钮点击事件。下面是如何在 Flutter 画布上渲染按钮的基本示例:


import 'package:flutter/material.dart';

void main() {
  runApp(MaterialApp(
    home: Scaffold(
      appBar: AppBar(
        title: Text('Canvas Buttons Example'),
      ),
      body: CanvasButtonDemo(),
    ),
  ));
}

class CanvasButtonDemo extends StatefulWidget {
  @override
  _CanvasButtonDemoState createState() => _CanvasButtonDemoState();
}

class _CanvasButtonDemoState extends State<CanvasButtonDemo> {
  List<Button> buttons = [];

  @override
  void initState() {
    super.initState();
    buttons.add(Button(50, 50, 100, 50, 'Button 1', onPressed: () {
      print('Button 1 pressed');
    }));
    buttons.add(Button(50, 150, 100, 50, 'Button 2', onPressed: () {
      print('Button 2 pressed');
    }));
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size(double.infinity, double.infinity),
      painter: CanvasButtonPainter(buttons),
    );
  }
}

class Button {
  final double x;
  final double y;
  final double width;
  final double height;
  final String label;
  final VoidCallback onPressed;

  Button(this.x, this.y, this.width, this.height, this.label, {required this.onPressed});
}

class CanvasButtonPainter extends CustomPainter {
  final List<Button> buttons;

  CanvasButtonPainter(this.buttons);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.fill;

    for (var button in buttons) {
      final rect = Rect.fromPoints(Offset(button.x, button.y), Offset(button.x + button.width, button.y + button.height));
      canvas.drawRect(rect, paint);

      final textPainter = TextPainter(
        text: TextSpan(
          text: button.label,
          style: TextStyle(color: Colors.white, fontSize: 20.0),
        ),
        textDirection: TextDirection.ltr,
      );

      textPainter.layout(minWidth: 0, maxWidth: button.width);
      textPainter.paint(canvas, Offset(button.x, button.y));

      // Add touch handling
      canvas.drawRect(rect, paint);
      canvas.drawRect(rect, Paint()..color = Colors.transparent);
      final buttonRect = rect.shift(Offset(0, size.height));
      canvas.drawRect(buttonRect, Paint()..color = Colors.transparent);

      final touchArea = Rect.fromPoints(rect.topLeft, buttonRect.bottomRight);
      canvas.drawRRect(
          RRect.fromRectAndRadius(touchArea, Radius.circular(8.0)), Paint()..color = Colors.transparent);
    }
  }

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


此代码定义一个 Button 类来存储按钮属性,如位置、大小、标签和 onPressed 回调。CanvasButtonPainter 类用于绘制画布上的按钮,它还处理触摸事件以检测按钮按下。 这是一个基本示例,您可以根据特定用例的需要进一步自定义它。

评论

0赞 JonathanLauxenRomano 10/23/2023
是的,我渲染了我的按钮,现在我的问题是其他问题,我在我的类 Sketch 中定义了一个使用转换的方法,但我看不到路径实时更新,更改只出现在末尾:(
0赞 fravolt 10/23/2023
看看答案底部的功能。您可以比较 和 ,如果某些字段已更改(您可以检查等),您可以返回,以便按钮将重新绘制shouldRepaintthisoldDelegatexytrue