Flutter 颤振中的自定义小部件引发事件不起作用属性
我需要一个自定义小部件在我的页面上画垂直和水平线,我可以在运行时调整小部件的大小。我将用于DrawLine的GestureDetector与paint和canvas相结合,因此我有一个名为Line的类,我可以在这个类上绘制我的线条 所以我在flatter中创建了一个自定义小部件,用于在运行时使用resize属性绘制垂直线 我在flifter上写这段代码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
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绘制具有相对位置而不是全局位置的线