我正在学习 Flutter,我想创建一个包含三个彩色方块的简单示例,我可以在窗口内用鼠标移动/拖动它们。然而,我希望方块的移动受到窗口面积的限制。我设法设置了位置下边界的限制(简单地说它不能小于零)但是我没有找到限制上边界的方法。我需要以某种方式获得大小(宽度和父部件的高度)。但是我没有找到任何方法来获取它。
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Moving Boxes',
home: MyMainPage(),
);
}
}
class MyMainPage extends StatelessWidget {
const MyMainPage({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: Stack(
children: <Widget>[
MovableBox(color: Colors.red, left: 100, top: 100),
MovableBox(color: Colors.yellow, left: 200, top: 50),
MovableBox(color: Colors.blue, left: 0, top: 0)
]
));
}
}
class MovableBox extends StatefulWidget {
const MovableBox({super.key, required this.color, this.top = 0, this.left = 0});
@override
State<MovableBox> createState() => _MovableBoxState();
final Color color;
final double top;
final double left;
}
class _MovableBoxState extends State<MovableBox> {
double _left = 0;
double _top = 0;
@override
void initState()
{
super.initState();
_left = widget.left;
_top = widget.top;
}
@override
Widget build(BuildContext context) {
return Positioned(
top: max(_top, 0), // here I limit the lower boundary but I would also like to limit the upper one
left: max(_left, 0),
width: 200,
height: 200,
child: Container(
color: widget.color,
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
_left += details.delta.dx;
_top += details.delta.dy;
});
},
),
),
);
}
}
我知道有一个名为
Draggable
的类应该做这样的事情。但出于学习目的,我想从较低级别的组件中实现它。
我猜我的设计可能是错误的。也许有几种方法可以实现这一目标。我想尽可能多地学习它们。
好的,经过更多的谷歌搜索,我发现了
MediaQuery.of(context)
所以解决方案是:
@override
Widget build(BuildContext context) {
final area = MediaQuery.of(context).size;
const width = 200.0;
const height = 200.0;
return Positioned(
top: min(max(_top, 0), area.height - height),
left: min(max(_left, 0), area.width - width),
width: width,
height: height,
child: Container(
color: widget.color,
child: GestureDetector(
onPanUpdate: (details) {
setState(() {
_left += details.delta.dx;
_top += details.delta.dy;
});
},
onPanEnd: (details) {
setState(() {
_top = min(max(_top, 0), area.height - height);
_left = min(max(_left, 0), area.width - width);
});
},
),
),
);
}
请注意,我还添加了
onPanEnd
处理程序以改进平移时的行为。