Flutter 颤振中的自定义小部件引发事件不起作用属性

Flutter 颤振中的自定义小部件引发事件不起作用属性,flutter,events,custom-widgets,Flutter,Events,Custom Widgets,我需要一个自定义小部件在我的页面上画垂直和水平线,我可以在运行时调整小部件的大小。我将用于DrawLine的GestureDetector与paint和canvas相结合,因此我有一个名为Line的类,我可以在这个类上绘制我的线条 所以我在flatter中创建了一个自定义小部件,用于在运行时使用resize属性绘制垂直线 我在flifter上写这段代码 import 'package:flutter/material.dart'; void main() => runApp(MyApp

我需要一个自定义小部件在我的页面上画垂直和水平线,我可以在运行时调整小部件的大小。我将用于DrawLine的GestureDetector与paint和canvas相结合,因此我有一个名为Line的类,我可以在这个类上绘制我的线条

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

我在flifter上写这段代码


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, height: 300),
          ],
        ),
      ),
    );
  }
}

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,
          left: widget.left - ballDiameter / 2,
          child: new ManipulatingBall(
            onDrag: (dx, 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;
  }
}

进口“包装:颤振/材料.省道”;
void main()=>runApp(MyApp());
类MyApp扩展了无状态小部件{
双倍高度=300;
双层顶=0;
左双=200;
@凌驾
小部件构建(构建上下文){
返回材料PP(
标题:“文本溢出演示”,
主题:主题数据(
主样本:颜色。蓝色,
),
家:脚手架(
主体:堆栈(
儿童:[
新抽绳等级(顶部:50,左侧:100,高度:400),
新抽绳等级(顶部:100,左侧:50,高度:300),
新抽绳等级(顶部:150,左侧:150,高度:300),
],
),
),
);
}
}
常数双球直径=20.0;
常数双冲程宽度=10.0;
类DrawLineClass扩展StatefulWidget{
DrawLineClass({Key-Key,this.top,this.left,this.height}):super(Key:Key);
双高;
双层顶;
左双;
@凌驾
_DrawLineClassState createState()=>\u DrawLineClassState();
}
类\u DrawLineClassState扩展状态{
@凌驾
小部件构建(构建上下文){
返回新堆栈(
儿童:[
行(开始:{“x”:widget.left,“y”:widget.top},结束:{“x”:widget.left,“y”:widget.height}),
//中上部
定位(
顶部:widget.top-球径/2,
左:widget.left-球径/2,
孩子:新的操纵球(
onDrag:(dx,dy){
设置状态(){
widget.top=widget.top+dy;
});
},
),
),
//底部中心
定位(
顶部:widget.height-球径/2,
左:widget.left-球径/2,
孩子:新的操纵球(
onDrag:(dx,dy){
var newHeight=widget.height+dy;
设置状态(){
widget.height=newHeight>0?newHeight:0;
});
},
),
),
],
);
}
}
类操纵球扩展StatefulWidget{
操纵球({Key-Key,this.onDrag}):超级(Key:Key);
功能性尿毒症;
@凌驾
_操纵BallState createState()=>_操纵BallState();
}
类_操纵BallState扩展状态{
双initX;
双重人格;
_手抹布(细节){
设置状态(){
initX=details.globalPosition.dx;
initY=details.globalPosition.dy;
});
}
_handleUpdate(详细信息){
var dx=details.globalPosition.dx-initX;
var dy=details.globalPosition.dy-initY;
initX=details.globalPosition.dx;
initY=details.globalPosition.dy;
widget.onDrag(dx,dy);
}
@凌驾
小部件构建(构建上下文){
返回新的手势检测器(
行为:HitTestBehavior.deferToChild,
onPanStart:_handleDrag,
onPanUpdate:_handleUpdate,
子:容器(
宽度:球径,
高度:球径,
装饰:盒子装饰(
颜色:颜色。蓝色。不透明度(0.5),
形状:BoxShape.circle,
),
),
);
}
}
类行扩展StatefulWidget{
最终地图开始;
最终地图结束;
行({this.start,this.end});
@凌驾
_LineState createState()=>\u LineState();
}
类_LineState使用SingleTickerProviderStateMixin扩展状态{
动画控制器_控制器;
@凌驾
void initState(){
super.initState();
_控制器=动画控制器(vsync:this);
}
@凌驾
无效处置(){
super.dispose();
_controller.dispose();
}
@凌驾
小部件构建(构建上下文){
返回自定义油漆(
size:size(MediaQuery.of(context).size.width,
MediaQuery.of(context.size.height),
画师:绘制线(开始:widget.start,结束:widget.end),
);
}
}
类DrawLine扩展了CustomPainter{
地图启动;
地图末端;
抽绳({this.start,this.end});
@凌驾
空心油漆(帆布,尺寸){
绘制线=新绘制()
…颜色=颜色。红色
..strokeCap=strokeCap.round
…style=PaintingStyle.fill
..冲程宽度=冲程宽度;
画布.绘制线(偏移量(起点[“x”]、起点[“y”]、偏移量(终点[“x”]、终点[“y”])、线);
}
@凌驾
bool应重新绘制(自定义代理){
//TODO:实现应重新绘制
返回true;
}
}
我在我的页面上画了3行,但只有最新的一行可以调整大小

有什么问题?

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