I have a Stack with 3 Positioned widgets with a GestureDetector as a child. I'm able to drag them, but I also want to bring the clicked one to the front as soon as you click it. I've tried lifting up a call to change state in the parent widget, but that does also exchange the afected widgets position.
Here is the full sample code (it's the body in a Scaffold. Any help will be appreciated
class DragBox extends StatefulWidget {
final Offset startPosition;
final Color color;
final String label;
final Function bringToTop;
DragBox({
this.startPosition,
this.color: const Color.fromRGBO(255, 255, 255, 1.0),
this.label,
this.bringToTop
});
@override
DragBoxState createState() => DragBoxState();
}
class DragBoxState extends State<DragBox> {
Offset position;
Offset _startPos;
@override
void initState() {
position = widget.startPosition;
super.initState();
}
@override
Widget build(BuildContext context) {
return Positioned(
left: position.dx,
top: position.dy,
child: GestureDetector(
onScaleStart: (details) {
//Store start conditions
_startPos = details.focalPoint;
widget.bringToTop(widget);
},
onScaleUpdate: (scaleDetails) {
setState(() {
position += scaleDetails.focalPoint - _startPos;
_startPos = scaleDetails.focalPoint;
});
},
child: _buildPart()
));
}
Widget _buildPart() {
return Container(
width: 100.0,
height: 100.0,
decoration: BoxDecoration(
border: Border.all(color: Color.fromARGB(255, 0, 0, 0), width: 1.0),
color: widget.color),
child: Text(
widget.label,
style: TextStyle(
color: Color.fromRGBO(255, 255, 255, 1.0),
//decoration: TextDecoration.none,
fontSize: 15.0,
),
),
);
}
}
class WorkTable extends StatefulWidget {
@override
WorkTableState createState() => WorkTableState();
}
class WorkTableState extends State<WorkTable> {
List<DragBox> dragParts = [];
@override
void initState() {
dragParts = [];
//dragParts = [];
dragParts.add(DragBox(
startPosition: Offset(0.0, 0.0),
color: Colors.red,
label: "Box1",
bringToTop: this.bringToTop,
));
dragParts.add(DragBox(
startPosition: Offset(50.0, 50.0),
color: Colors.red,
label: "Box2",
bringToTop: this.bringToTop,
));
dragParts.add(DragBox(
startPosition: Offset(100.0, 100.0),
color: Colors.blue,
label: "Box3",
bringToTop: this.bringToTop,
));
super.initState();
}
@override
Widget build(BuildContext context) {
for(DragBox d in dragParts){
print(d.label);
}
return Stack(
children: dragParts,
);
}
void bringToTop(Widget widget) {
setState(() {
dragParts.remove(widget);
dragParts.add(widget);
});
}
}
The strange part happens here
void bringToTop(Widget widget) {
setState(() {
dragParts.remove(widget);
dragParts.add(widget);
});
}
Instead of changing only depth, positions are also exchanged
Row's mainAxis is horizontal and cross Axis to Row's main Axis is vertical. We can align children horizontally using MainAxisAlignment and vertically using CrossAxisAlignment in that row.
SizedBox is a built-in widget in flutter SDK. It is a simple box with a specified size. It can be used to set size constraints to the child widget, put an empty SizedBox between the two widgets to get some space in between, or something else. It is somewhat similar to a Container widget with fewer properties.
Create your own widget stacksTouch and hold an app or empty area on the Home Screen or Today View until the apps jiggle. Drag a widget on top of another widget. You can stack up to 10 widgets. Tap Done.
Adding a GlobalKey
(or some other key) to your widgets should fix the problem:
dragParts.add(DragBox(
key: GlobalKey(),
startPosition: Offset(0.0, 0.0),
color: Colors.red,
label: "Box1",
bringToTop: this.bringToTop,
));
dragParts.add(DragBox(
key: GlobalKey(),
startPosition: Offset(50.0, 50.0),
color: Colors.red,
label: "Box2",
bringToTop: this.bringToTop,
));
dragParts.add(DragBox(
key: GlobalKey(),
startPosition: Offset(100.0, 100.0),
color: Colors.blue,
label: "Box3",
bringToTop: this.bringToTop,
));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With