flutter - 用手势检测器拖动
问题描述
我写了一个代码来拖动带有手势检测器的盒子,它可以工作。然后我重构了代码以便于阅读,它也可以工作,但运行速度很慢。有什么问题,我该如何解决?
我尝试将值打印到控制台,那里没有任何问题。
我写了一个代码来拖动带有手势检测器的盒子,它可以工作。然后我重构了代码以便于阅读,它也可以工作,但运行速度很慢。有什么问题,我该如何解决?
我尝试将值打印到控制台,那里没有任何问题。
我写了一个代码来拖动带有手势检测器的盒子,它可以工作。然后我重构了代码以便于阅读,它也可以工作,但运行速度很慢。有什么问题,我该如何解决?
我尝试将值打印到控制台,那里没有任何问题。
// old code that works
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
//so i can pass the widget size downward
body: Window(
size: MediaQuery.of(context).size,
),
);
}
}
class Window extends StatefulWidget {
final Size size;
const Window({Key key,@required this.size}) : super(key: key);
@override
_WindowState createState() => _WindowState();
}
class _WindowState extends State<Window> {
//for reference later
final boxSize = Size.square(100);
Offset firstBoxPosition = Offset.zero;
Offset secondBoxPosition = Offset.zero;
Offset thirdBoxPosition = Offset.zero;
@override
void initState() {
super.initState();
//so it starts at the center of the window
firstBoxPosition = widget.size / 2 - boxSize / 2 as Offset;
secondBoxPosition = widget.size / 4 - boxSize / 4 as Offset;
thirdBoxPosition = widget.size / 1.25 - boxSize / 1 as Offset;
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Positioned(
top: firstBoxPosition.dy,
left: firstBoxPosition.dx,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details){
setState(() {
//add the previous state of the position to the current state of the drag
final offset = details.delta + firstBoxPosition;
//so it doesn't go out of bounds
//The bound here is zero (the origin) and the size of the window
final x = offset.dx.clamp(0.0, widget.size.width - boxSize.width);
final y = offset.dy.clamp(0.0, widget.size.height - boxSize.height);
firstBoxPosition = Offset(x,y);
});
},
child: SizedBox.fromSize(
size: boxSize,
child: Material(color: Colors.green,),
),
),
),
Positioned(
top: secondBoxPosition.dy,
left: secondBoxPosition.dx,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details){
setState(() {
//add the previous state of the position to the current state of the drag
final offset = details.delta + secondBoxPosition;
//so it doesn't go out of bounds
//The bound here is zero (the origin) and the size of the window
final x = offset.dx.clamp(0.0, widget.size.width - boxSize.width);
final y = offset.dy.clamp(0.0, widget.size.height - boxSize.height);
secondBoxPosition = Offset(x,y);
});
},
child: SizedBox.fromSize(
size: boxSize,
child: Material(color: Colors.blue,),
),
),
),
Positioned(
top: thirdBoxPosition.dy,
left: thirdBoxPosition.dx,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details){
setState(() {
//add the previous state of the position to the current state of the drag
final offset = details.delta + thirdBoxPosition;
//so it doesn't go out of bounds
//The bound here is zero (the origin) and the size of the window
final x = offset.dx.clamp(0.0, widget.size.width - boxSize.width);
final y = offset.dy.clamp(0.0, widget.size.height - boxSize.height);
thirdBoxPosition = Offset(x,y);
});
},
child: SizedBox.fromSize(
size: boxSize,
child: Material(color: Colors.red,),
),
),
),
],
);
}
}
//refactored code that's moving slowly
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
//so i can pass the widget size downward
body: Window(
size: MediaQuery.of(context).size,
),
);
}
}
class Window extends StatefulWidget {
const Window({Key key, @required this.size}) : super(key: key);
final Size size;
@override
_WindowState createState() => _WindowState();
}
class _WindowState extends State<Window> {
//for reference later
final boxSize = Size.square(100);
Offset firstBoxPosition = Offset.zero;
Offset secondBoxPosition = Offset.zero;
Offset thirdBoxPosition = Offset.zero;
Rect get windowBounds => Offset.zero & widget.size;
@override
void initState() {
super.initState();
// This is not necessary but good for visualization
final boxCenter = boxSize / 2;
firstBoxPosition = widget.size / 2 - boxCenter as Offset;
secondBoxPosition = widget.size / 4 - boxCenter as Offset;
thirdBoxPosition = widget.size / 1.25 - boxCenter as Offset;
}
@override
Widget build(BuildContext context) {
return Stack(
children: [
Box(
position: firstBoxPosition,
size: boxSize,
color: Colors.red,
bounds: windowBounds,
onDragged: (position) {
setState(() {
firstBoxPosition = position;
});
},
),
Box(
position: secondBoxPosition,
size: boxSize,
color: Colors.green,
bounds: windowBounds,
onDragged: (position) {
setState(() {
secondBoxPosition = position;
});
},
),
Box(
position: thirdBoxPosition,
size: boxSize,
color: Colors.blue,
bounds: windowBounds,
onDragged: (position) {
setState(() {
thirdBoxPosition = position;
});
},
),
],
);
}
}
class Box extends Positioned {
Box({
Key key,
@required Rect bounds,
@required Size size,
@required Offset position,
@required Color color,
@required ValueChanged<Offset> onDragged,
}) : super(
key: key,
top: position.dy,
left: position.dx,
width: size.width,
height: size.height,
child: GestureDetector(
onPanUpdate: (DragUpdateDetails details) {
//add the previous state of the position to the current state of the drag
final offset = details.delta + position;
//so it doesn't go out of bounds
final x = offset.dx.clamp(bounds.left, bounds.right - size.width);
final y = offset.dy.clamp(bounds.top, bounds.bottom - size.height);
onDragged.call(Offset(x, y));
},
child: Material(color: color),
),
);
}
解决方案
推荐阅读
- hazelcast - 如何始终将数据发送到 localMember 实例
- mysql - 如何逐行更新从过程中的游标中检索到的数据库值?
- c++ - 使具有引用成员的类可复制和可移动
- php - ImageMagick PHP Docker 版本问题
- r - R 函数registerDoParallel在多核计算中有什么用
- react-native - 使用 WSL2 运行时如何将手机连接到 expo
- java - 有没有办法阻止活动在被调用后自行关闭?
- php - 仅更改数据库给出 sess_write_close() 错误
- javascript - 在子集合中查询?
- node.js - 在同一台机器上运行具有不同配置文件的同一应用程序的两个实例是否可能?