Flutter; Draggable Widget
Draggable widgets helps to drag its child widgets anywhere within the boundaries of the parent widget. So, if you have a draggable item in scaffold, then you can drag it anywhere in the screen. If you have it in a container with size constrains then you can drag the child item anywhere inside the container. Once the child goes out of the parent container, it will no longer be available to drag.
Lets build a drag item in a scaffold first.
import 'package:flutter/material.dart';void main() => runApp(
new MyApp(),
);class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Draggable',
home: Drag(),
);
}
}class Drag extends StatefulWidget {
Drag({Key key}) : super(key: key);
@override
_DragState createState() => _DragState();
}class _DragState extends State<Drag> {double top = 0;
double left = 0;@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Draggable(
child: Container(
padding: EdgeInsets.only(top: top, left: left),
child: DragItem(),
),
feedback: Container(
padding: EdgeInsets.only(top: top, left: left),
child: DragItem(),
),
childWhenDragging: Container(
padding: EdgeInsets.only(top: top, left: left),
child: DragItem(),
),
onDragCompleted: () {},
onDragEnd: (drag) {
setState(() {
top = top + drag.offset.dy < 0 ? 0 : top + drag.offset.dy;
left = left + drag.offset.dx < 0 ? 0 : left + drag.offset.dx;
});
},
),
),
);
}
}class DragItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Icon(
IconData(57744, fontFamily: 'MaterialIcons'),
size: 36,
);
}
}
Now, lets have a container and drag the icons inside it. Even if we move the icon out of the box it should stay at the edges.
To do that lets place a container of 300*300 and place draggable widget inside it. Our drag item has a size of 30. When ever the drag end position is outside 300–30 it should’nt go outside the container. Hence we do a calc and restrict the positions.
import 'package:flutter/material.dart';void main() => runApp(
new MyApp(),
);class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Draggable',
home: Drag(),
);
}
}class Drag extends StatefulWidget {
Drag({Key key}) : super(key: key);
@override
_DragState createState() => _DragState();
}class _DragState extends State<Drag> {
double top = 0;
double left = 0;@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
alignment: Alignment.topLeft,
margin: EdgeInsets.all(30),
height: 300,
width: 300,
color: Colors.indigo.shade100,
child: Draggable(
child: Container(
padding: EdgeInsets.only(top: top, left: left),
child: DragItem(),
),
feedback: Container(
padding: EdgeInsets.only(top: top, left: left),
child: DragItem(),
),
childWhenDragging: Container(
padding: EdgeInsets.only(top: top, left: left),
child: DragItem(),
),
onDragCompleted: () {},
onDragEnd: (drag) {
setState(() {
if((top + drag.offset.dy) > (300.0 - 30.0)){
top = (300.0 - 30.0);
}else if((top + drag.offset.dy-30.0) < 0.0){
top = 0;
}else{
top = top + drag.offset.dy-30.0;
}if((left + drag.offset.dx) > (300.0 - 30.0)){
left = (300.0 - 30.0);
}else if((left + drag.offset.dx-30.0) < 0.0){
left = 0;
}else{
left = left + drag.offset.dx-30.0;
}});
},
),
),
);
}
}class DragItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Icon(
IconData(57744, fontFamily: 'MaterialIcons'),
size: 30,
);
}
}
Out put will looks like below.