当窗口小部件包装在InteractiveViewer中时,Flutter onPanStart会延迟调用 [英] Flutter onPanStart invokes late when the widget is wrapped inside InteractiveViewer

查看:66
本文介绍了当窗口小部件包装在InteractiveViewer中时,Flutter onPanStart会延迟调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只是有一个简单的容器,该容器的右中间具有调整大小的手柄,这意味着可以使用该手柄调整容器的大小.它包装在 InteractiveViewer 小部件中.

I just have a simple container which has a resize handle on center right which means the container can be resized using that handle. It is wrapped inside InteractiveViewer widget.

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

void main() {
  debugPaintSizeEnabled = true;
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  double _width = 300;
  double _height = 200;

  @override
  Widget build(BuildContext context) {
    final m = MediaQuery.of(context);
    return Scaffold(
      body: SafeArea(
        child: Container(
          height: m.size.height,
          width: m.size.width,
          child: InteractiveViewer(
            maxScale: 30,
            child: Stack(
              children: <Widget>[
                Container(height: _height, width: _width, color: Colors.red),
                Positioned(
                  top: _height / 2 - 10,
                  left: _width - 20,
                  child: GestureDetector(
                    onPanStart: (details) {
                      print("PAN STARTED");
                    },
                    onPanUpdate: (details) {
                      final delta = details.delta;
                      setState(() {
                        _width = _width + delta.dx;
                      });
                    },
                    child: Container(height: 20, width: 20, color: Colors.blue),
                  ),
                )
              ],
            ),
          ),
        ),
      ),
    );
  }
}

问题是 onPanStart 在初始拖动后很晚才调用.任何帮助将不胜感激.

The problem is onPanStart invokes a lot late after the initial drag. Any help would be greatly appreciated.

注意:此问题无法在DartPad中复制.在DartPad中,它可以正常工作.该问题只能在模拟器/电话中看到.

Note: This problem cannot be replicated in DartPad. In DartPad it works fine. The problem can only be seen in simulators/phones.

推荐答案

我找到了解决此问题的方法.只需使用Listener而不是GestureDetector(它可以替代大多数参数:onPanStart-> onPointerDown,onPanUpdate-> onPointerMove).有了Listener,就不会有延迟.

I found a fix for this issue. Just use Listener instead of GestureDetector (it has substitutes for the most parameters: onPanStart -> onPointerDown, onPanUpdate -> onPointerMove). With Listener, there will be no delay.

最小代码示例:

import 'package:flutter/material.dart';

class IssueExamplePage extends StatefulWidget {
  @override
  _IssueExamplePageState createState() => _IssueExamplePageState();
}

class _IssueExamplePageState extends State<IssueExamplePage> {
  bool drawingBlocked = false;
  List<Offset> points;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Container(
          child: InteractiveViewer(
            child: AbsorbPointer(
              absorbing: drawingBlocked,
              child: Listener(
                 onPointerMove: (details) {
                  RenderBox renderBox = context.findRenderObject();
                  Offset cursorLocation = renderBox.globalToLocal(details.localPosition);

                  setState(() {
                    points = List.of(points)..add(cursorLocation);
                  });
                },
                child: CustomPaint(
                  painter: MyPainter(points),
                  size: Size.infinite
                ),
              ),
            ),
          ),
        ),
      ),
      floatingActionButton: Column(
        children: [
          FloatingActionButton(
            child: Icon(Icons.clear),
            onPressed: () {
              setState(() {
                points = [];
              });
            }
          ),
          FloatingActionButton(
            child: Icon(drawingBlocked? CupertinoIcons.hand_raised_fill : CupertinoIcons.hand_raised),
            onPressed: () {
              drawingBlocked = !drawingBlocked;
            }
          ),
        ],
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  MyPainter(this.points);
  List<Offset> points;
  Paint paintBrush = Paint()
    ..color = Colors.blue
    ..strokeWidth = 5
    ..strokeJoin = StrokeJoin.round;

  @override
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < points.length - 1; i++) {
      canvas.drawLine(points[i], points[i + 1], paintBrush);
    }
  }
  
  @override
  bool shouldRepaint(MyPainter oldDelegate) {
    return points != oldDelegate.points;
  }
}

这篇关于当窗口小部件包装在InteractiveViewer中时,Flutter onPanStart会延迟调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆