微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

自定义窗口小部件引发事件在flutter中不起作用

如何解决自定义窗口小部件引发事件在flutter中不起作用

我需要一个自定义小部件来在页面上绘制垂直和水平线,我可以在运行时调整小部件的大小。我将DrawLine的GestureDetector与油漆和画布结合在一起,所以我有一个名为 Line 的类,并且可以在此类上绘制线条

所以我在Flutter中创建了一个自定义小部件,用于在运行时使用resize属性绘制垂直线

我在扑扑的时候写这段代码


import 'package:Flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  double height = 300;
  double top = 0;
  double left = 200;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Text Overflow Demo',theme: ThemeData(
        primarySwatch: Colors.blue,),home: Scaffold(
        body: Stack(
          children: <Widget>[
            new DrawLineClass(top: 50,left: 100,height: 400),new DrawLineClass(top: 100,left: 50,height: 300),new DrawLineClass(top: 150,left: 150,],);
  }
}

const double ballDiameter = 20.0;
const double strokeWidth = 10.0;

class DrawLineClass extends StatefulWidget {
  DrawLineClass({Key key,this.top,this.left,this.height}) : super(key: key);

  double height;
  double top;
  double left;

  @override
  _DrawLineClassstate createState() => _DrawLineClassstate();
}

class _DrawLineClassstate extends State<DrawLineClass> {
  @override
  Widget build(BuildContext context) {
    return new Stack(
      children: <Widget>[
        Line(start: {"x": widget.left,"y": widget.top},end: {"x": widget.left,"y": widget.height}),// top middle
        Positioned(
          top: widget.top - ballDiameter / 2,left: widget.left - ballDiameter / 2,child: new ManipulatingBall(
            onDrag: (dx,dy) {
              setState(() {
                widget.top = widget.top + dy;
              });
            },// bottom center
        Positioned(
          top: widget.height - ballDiameter / 2,dy) {
              var newHeight = widget.height + dy;

              setState(() {
                widget.height = newHeight > 0 ? newHeight : 0;
              });
            },);
  }
}

class ManipulatingBall extends StatefulWidget {
  ManipulatingBall({Key key,this.onDrag}) : super(key: key);

  Function onDrag;

  @override
  _ManipulatingBallState createState() => _ManipulatingBallState();
}

class _ManipulatingBallState extends State<ManipulatingBall> {
  double initX;
  double initY;

  _handleDrag(details) {
    setState(() {
      initX = details.globalPosition.dx;
      initY = details.globalPosition.dy;
    });
  }

  _handleUpdate(details) {
    var dx = details.globalPosition.dx - initX;
    var dy = details.globalPosition.dy - initY;
    initX = details.globalPosition.dx;
    initY = details.globalPosition.dy;
    widget.onDrag(dx,dy);
  }

  @override
  Widget build(BuildContext context) {
    return new GestureDetector(
      behavior: HitTestBehavior.defertochild,onPanStart: _handleDrag,onPanUpdate: _handleUpdate,child: Container(
        width: ballDiameter,height: ballDiameter,decoration: Boxdecoration(
          color: Colors.blue.withOpacity(0.5),shape: BoxShape.circle,);
  }
}

class Line extends StatefulWidget {
  final Map<String,double> start;
  final Map<String,double> end;
  Line({this.start,this.end});

  @override
  _Linestate createState() => _Linestate();
}

class _Linestate extends State<Line> with SingleTickerProviderStateMixin {
  AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(vsync: this);
  }

  @override
  void dispose() {
    super.dispose();
    _controller.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      size: Size(MediaQuery.of(context).size.width,MediaQuery.of(context).size.height),painter: DrawLine(start: widget.start,end: widget.end),);
  }
}

class DrawLine extends CustomPainter {
  Map<String,double> start;
  Map<String,double> end;
  DrawLine({this.start,this.end});

  @override
  void paint(Canvas canvas,Size size) {
    Paint line = new Paint()
      ..color = Colors.red
      ..strokeCap = strokeCap.round
      ..style = PaintingStyle.fill
      ..strokeWidth = strokeWidth;
    canvas.drawLine(Offset(start["x"],start["y"]),Offset(end["x"],end["y"]),line);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    // Todo: implement shouldRepaint
    return true;
  }
}

我在页面上画了3行,但只有最新的行可以调整大小
有什么问题吗?

解决方法

每条线在整个屏幕上绘制,第三条线覆盖第一条和第二条线,第一条线和第二条线都不能接收GestureDetector事件。相反,您可以使用LayoutBuidler绘制相对位置而非全局位置的线。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。