扑来 - 将小部件拖出初始屏幕空间
我需要在“无限”画布上拖动物品。 该代码允许拖动项目并在容器内移动。
但是,如果我在容器内移动并将项目拖出原始屏幕空间(从较轻的容器中)消失。
我添加了一个较轻的容器来帮助可视化问题: 原始屏幕视图的限制
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' as vector;
import 'package:matrix_gesture_detector/matrix_gesture_detector.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Monitor',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
//canvasColor: Color.fromRGBO(42, 48, 68, 100),
),
home: const MyHomePage(title: 'Monitor'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey _paintKey = GlobalKey();
Offset _offset = const Offset(0,0);
List<Widget> widgets = [];
Matrix4 matrix = Matrix4.identity();
void _addElement()
{
setState(() {
widgets.add(PositionedDraggableIcon(top: 0, left: 0, offset: matrix));
});
}
@override
Widget build(BuildContext context) {
return MatrixGestureDetector(
onMatrixUpdate: (Matrix4 m, Matrix4 tm, Matrix4 sm, Matrix4 rm) {
setState(() {
matrix = m;
for (Widget w in widgets) {
(w as PositionedDraggableIcon).updateMatrix(matrix);
}
});
},
clipChild: false,
child: Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Container(
color: Colors.grey,
child: Transform(
transform: matrix,
child: Container(
color: Colors.grey[400],
child: Stack(
children: widgets,
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _addElement,
tooltip: 'Add icon',
child: const Icon(Icons.add),
),
)
);
}
}
class PositionedDraggableIcon extends StatefulWidget {
final double top;
final double left;
Matrix4 offset;
void updateMatrix(Matrix4 matrix)
{
offset = matrix;
/*setState(() {
matrix = matrix;
});*/
}
PositionedDraggableIcon({Key? key,
required this.top,
required this.left,
required this.offset,}) : super(key: key);
@override
_PositionedDraggableIconState createState() => _PositionedDraggableIconState();
}
class _PositionedDraggableIconState extends State<PositionedDraggableIcon> {
GlobalKey _key = GlobalKey();
late double top, left;
late double xOff, yOff;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
top = widget.top;
left = widget.left;
super.initState();
}
void _getRenderOffsets() {
final RenderBox renderBoxWidget = _key.currentContext?.findRenderObject() as RenderBox;
vector.Vector3 lTrans = widget.offset.getTranslation();
final offset = renderBoxWidget.localToGlobal(Offset(-lTrans.x, -lTrans.y));
yOff = offset.dy - top;
xOff = offset.dx - left;
}
void _afterLayout(_) {
_getRenderOffsets();
}
@override
Widget build(BuildContext context) {
return Positioned(
key: _key,
top: top,
left: left,
child: Draggable(
child: Icon(Icons.input),
feedback: Icon(Icons.input),
childWhenDragging: Container(),
onDragEnd: (drag) {
setState(() {
top = drag.offset.dy - yOff - widget.offset.getTranslation().y;
left = drag.offset.dx - xOff - widget.offset.getTranslation().x;
});
},
),
);
}
}
I need to drag items around an "infinite" canvas.
The code allows to drag items and to move inside the container.
But if I move inside the container and drag the items out of the original screen space (out of the lighter container), they disappear.
I added a lighter container to help visualise the problem :
Items in limit of the original screen view
import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' as vector;
import 'package:matrix_gesture_detector/matrix_gesture_detector.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Monitor',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
//canvasColor: Color.fromRGBO(42, 48, 68, 100),
),
home: const MyHomePage(title: 'Monitor'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey _paintKey = GlobalKey();
Offset _offset = const Offset(0,0);
List<Widget> widgets = [];
Matrix4 matrix = Matrix4.identity();
void _addElement()
{
setState(() {
widgets.add(PositionedDraggableIcon(top: 0, left: 0, offset: matrix));
});
}
@override
Widget build(BuildContext context) {
return MatrixGestureDetector(
onMatrixUpdate: (Matrix4 m, Matrix4 tm, Matrix4 sm, Matrix4 rm) {
setState(() {
matrix = m;
for (Widget w in widgets) {
(w as PositionedDraggableIcon).updateMatrix(matrix);
}
});
},
clipChild: false,
child: Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Container(
color: Colors.grey,
child: Transform(
transform: matrix,
child: Container(
color: Colors.grey[400],
child: Stack(
children: widgets,
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _addElement,
tooltip: 'Add icon',
child: const Icon(Icons.add),
),
)
);
}
}
class PositionedDraggableIcon extends StatefulWidget {
final double top;
final double left;
Matrix4 offset;
void updateMatrix(Matrix4 matrix)
{
offset = matrix;
/*setState(() {
matrix = matrix;
});*/
}
PositionedDraggableIcon({Key? key,
required this.top,
required this.left,
required this.offset,}) : super(key: key);
@override
_PositionedDraggableIconState createState() => _PositionedDraggableIconState();
}
class _PositionedDraggableIconState extends State<PositionedDraggableIcon> {
GlobalKey _key = GlobalKey();
late double top, left;
late double xOff, yOff;
@override
void initState() {
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
top = widget.top;
left = widget.left;
super.initState();
}
void _getRenderOffsets() {
final RenderBox renderBoxWidget = _key.currentContext?.findRenderObject() as RenderBox;
vector.Vector3 lTrans = widget.offset.getTranslation();
final offset = renderBoxWidget.localToGlobal(Offset(-lTrans.x, -lTrans.y));
yOff = offset.dy - top;
xOff = offset.dx - left;
}
void _afterLayout(_) {
_getRenderOffsets();
}
@override
Widget build(BuildContext context) {
return Positioned(
key: _key,
top: top,
left: left,
child: Draggable(
child: Icon(Icons.input),
feedback: Icon(Icons.input),
childWhenDragging: Container(),
onDragEnd: (drag) {
setState(() {
top = drag.offset.dy - yOff - widget.offset.getTranslation().y;
left = drag.offset.dx - xOff - widget.offset.getTranslation().x;
});
},
),
);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想解决了我的问题:
clipbehavior:clip.none
在堆栈中。而且图标是在原始屏幕视图之外拖动的,而不会被剪裁。
I figured out to solve my problem:
clipBehavior: Clip.none
in the Stack.And the icons are draggable outside the original screen view without being clipped.