在画布上与GestureDetector结合使用

时间:2019-03-10 00:39:50

标签: flutter

我想在用户触摸移动时绘制并更新一个圆。.因此我发现了一些与我想要的东西(Flutter - Creating a custom control with Flutter)相似的东西

这是已接受答案的复制粘贴代码(只需将其复制粘贴到main.dart中,您就可以看到输出):

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

void main() {
  runApp(new TouchTest());
}

class TouchTest extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Touch Test',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new Scaffold(
        appBar: new AppBar(
          title: const Text('Test'),
        ),
        body: new Container(

          decoration: new BoxDecoration(
            color: Colors.white,
            border: new Border.all(
              color: Colors.black,
              width: 2.0,
            ),
          ),
          child: new Center(
            child: new TouchControl()
          ),
        ),
      )
    );
  }
}

class TouchControl extends StatefulWidget {
  final double xPos;
  final double yPos;
  final ValueChanged<Offset> onChanged;

  const TouchControl({Key key,
    this.onChanged,
    this.xPos:0.0,
    this.yPos:0.0}) : super(key: key);

  @override
  TouchControlState createState() => new TouchControlState();
}

/**
 * Draws a circle at supplied position.
 *
 */
class TouchControlState extends State<TouchControl> {
  double xPos = 0.0;
  double yPos = 0.0;

  GlobalKey _painterKey = new GlobalKey();

  void onChanged(Offset offset) {
    final RenderBox referenceBox = context.findRenderObject();
    Offset position = referenceBox.globalToLocal(offset);
    if (widget.onChanged != null)
      widget.onChanged(position);

    setState(() {
      xPos = position.dx;
      yPos = position.dy;
    });
  }

  @override
  bool hitTestSelf(Offset position) => true;

  @override
  void handleEvent(PointerEvent event, BoxHitTestEntry entry) {
    if (event is PointerDownEvent ) {
      // ??
    }
  }

  void _handlePanStart(DragStartDetails details) {
    onChanged(details.globalPosition);
  }

  void _handlePanEnd(DragEndDetails details) {
    print('end');
    // TODO
  }

  void _handlePanUpdate(DragUpdateDetails details) {
    onChanged(details.globalPosition);
  }

  @override
  Widget build(BuildContext context) {
    return new ConstrainedBox(
      constraints: new BoxConstraints.expand(),
      child: new GestureDetector(
        behavior: HitTestBehavior.opaque,
        onPanStart:_handlePanStart,
        onPanEnd: _handlePanEnd,
        onPanUpdate: _handlePanUpdate,
        child: new CustomPaint(
          size: new Size(xPos, yPos),
          painter: new TouchControlPainter(xPos, yPos),
        ),
      ),
    );
  }
}

class TouchControlPainter extends CustomPainter {
  static const markerRadius = 10.0;
  final double xPos;
  final double yPos;

  TouchControlPainter(this.xPos, this.yPos);

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

    canvas.drawCircle(new Offset(xPos, yPos), markerRadius, paint);
  }


  @override
  bool shouldRepaint(TouchControlPainter old) => xPos != old.xPos && yPos !=old.yPos;
}

问题在于,它运行速度非常慢,在iOS和Android上均远未达到60fps,这要好一些,但仍不能达到60fps。

有人可以解释出什么问题吗?

1 个答案:

答案 0 :(得分:0)

我已在本地运行代码,并且 iOS 应用程序似乎以可接受的帧速率 (30fps) 运行,其中呈现蓝色圆圈。延迟可能是由在 setState() 上重绘画布的速率引起的。虽然我同意帧速率在 Android 上似乎更好每秒 3~4 帧。

iOS 演示

iOS demo

Android 演示

Android demo

我建议更新您的 Flutter 版本,看看它现在是否比以前的性能运行得更好。这是我当前的设置。

[✓] Flutter (Channel stable, 2.2.1, on macOS 11.5 20G71 darwin-x64, locale en)
    • Flutter version 2.2.1
    • Framework revision 02c026b03c (9 weeks ago), 2021-05-27 12:24:44 -0700
    • Engine revision 0fdb562ac8
    • Dart version 2.13.1