admin管理员组文章数量:1278825
I want to have 2 movable widgets in a flutter's stack. I created a stack with red and blue containers, wrapped with GestureDetector and Positioned and they moved well.
when I tried to have the item that is touched on top of the other, I got a phenoment that when I try moving the red container, the blue actually moves, and in the code below, I get the first printing onPanStart:red, followed by the printing:blue is moved If i first touch the element I want to move, and only then moves it, it moves ok
note, that my original problem had a list of widgets in the stack, in this example, I narrowed it down to 2 basic elements.
why is the wrong elemnt moves?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Draggable Containers with Z-Order',
home: Scaffold(
appBar: AppBar(title: Text('Draggable Containers with Z-Order')),
body: DraggableStack(),
),
);
}
}
class DraggableStack extends StatefulWidget {
@override
_DraggableStackState createState() => _DraggableStackState();
}
class _DraggableStackState extends State<DraggableStack> {
// Starting positions for the containers.
Offset redPosition = Offset(50, 50);
Offset bluePosition = Offset(200, 200);
// True if red container is on top, false if blue container is on top.
bool redOnTop = false;
@override
Widget build(BuildContext context) {
// Create the red container widget.
Widget redContainer = Positioned(
left: redPosition.dx,
top: redPosition.dy,
child: GestureDetector(
onPanStart: (_) {
setState(() {
redOnTop = true;
print("onPanStart:red");
});
},
onPanUpdate: (details) {
setState(() {
redPosition += details.delta;
print("red is moved");
});
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
);
// Create the blue container widget.
Widget blueContainer = Positioned(
left: bluePosition.dx,
top: bluePosition.dy,
child: GestureDetector(
onPanStart: (_) {
setState(() {
redOnTop = false;
print("onPanStart:blue");
});
},
onPanUpdate: (details) {
setState(() {
bluePosition += details.delta;
print("blue is moved");
});
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
);
// Render the Stack so that the touched container is above.
return Stack(
children: redOnTop
? [blueContainer, redContainer] // Red on top.
: [redContainer, blueContainer], // Blue on top.
);
}
}
I want to have 2 movable widgets in a flutter's stack. I created a stack with red and blue containers, wrapped with GestureDetector and Positioned and they moved well.
when I tried to have the item that is touched on top of the other, I got a phenoment that when I try moving the red container, the blue actually moves, and in the code below, I get the first printing onPanStart:red, followed by the printing:blue is moved If i first touch the element I want to move, and only then moves it, it moves ok
note, that my original problem had a list of widgets in the stack, in this example, I narrowed it down to 2 basic elements.
why is the wrong elemnt moves?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Draggable Containers with Z-Order',
home: Scaffold(
appBar: AppBar(title: Text('Draggable Containers with Z-Order')),
body: DraggableStack(),
),
);
}
}
class DraggableStack extends StatefulWidget {
@override
_DraggableStackState createState() => _DraggableStackState();
}
class _DraggableStackState extends State<DraggableStack> {
// Starting positions for the containers.
Offset redPosition = Offset(50, 50);
Offset bluePosition = Offset(200, 200);
// True if red container is on top, false if blue container is on top.
bool redOnTop = false;
@override
Widget build(BuildContext context) {
// Create the red container widget.
Widget redContainer = Positioned(
left: redPosition.dx,
top: redPosition.dy,
child: GestureDetector(
onPanStart: (_) {
setState(() {
redOnTop = true;
print("onPanStart:red");
});
},
onPanUpdate: (details) {
setState(() {
redPosition += details.delta;
print("red is moved");
});
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
);
// Create the blue container widget.
Widget blueContainer = Positioned(
left: bluePosition.dx,
top: bluePosition.dy,
child: GestureDetector(
onPanStart: (_) {
setState(() {
redOnTop = false;
print("onPanStart:blue");
});
},
onPanUpdate: (details) {
setState(() {
bluePosition += details.delta;
print("blue is moved");
});
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
);
// Render the Stack so that the touched container is above.
return Stack(
children: redOnTop
? [blueContainer, redContainer] // Red on top.
: [redContainer, blueContainer], // Blue on top.
);
}
}
Share
Improve this question
asked Feb 23 at 21:35
Ravid GabbayRavid Gabbay
234 bronze badges
2 Answers
Reset to default 0Your problem is the stack, when you tap on a GestureDetector the stack rebuilds and that's why it's having conflicts
// Render the Stack so that the touched container is above.
return Stack(
children: redOnTop
? [blueContainer, redContainer] // Red on top.
: [redContainer, blueContainer], // Blue on top.
);
If you try setting this logic in each, you will see that when you try and drag it, they don't move:
onPanUpdate: (details) {
if(!redOnTop){
setState(() {
bluePosition += details.delta;
print("blue is moved");
});
}
},
You may have to use something different than the stack with the variable, to avoid rebuilds that conflict with you inner components.
Try this package to change the z-index dinamically https://pub.dev/packages/indexed
I have found the solution. Adding key:Valuekey() to the Positioned elements solved the problem. the key should be such that it is fixed for the container, and not based on the index in the stack (which changes all the time) it seems that without the key, the rebuild of the stack causes the gesturedetection to be linked with the index in the stack, and not with the correct element
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Draggable Containers with Z-Order',
home: Scaffold(
appBar: AppBar(title: Text('Draggable Containers with Z-Order')),
body: DraggableStack(),
),
);
}
}
class DraggableStack extends StatefulWidget {
@override
_DraggableStackState createState() => _DraggableStackState();
}
class _DraggableStackState extends State<DraggableStack> {
// Starting positions for the containers.
Offset redPosition = Offset(50, 50);
Offset bluePosition = Offset(200, 200);
// True if red container is on top, false if blue container is on top.
bool redOnTop = false;
@override
Widget build(BuildContext context) {
// Create the red container widget.
Widget redContainer = Positioned(
key: ValueKey(1),
left: redPosition.dx,
top: redPosition.dy,
child: GestureDetector(
onPanStart: (_) {
setState(() {
redOnTop = true;
print("onPanStart:red");
});
},
onPanUpdate: (details) {
setState(() {
redPosition += details.delta;
print("red is moved");
});
},
child: Container(
width: 100,
height: 100,
color: Colors.red,
),
),
);
// Create the blue container widget.
Widget blueContainer = Positioned(
key: ValueKey(2),
left: bluePosition.dx,
top: bluePosition.dy,
child: GestureDetector(
onPanStart: (_) {
setState(() {
redOnTop = false;
print("onPanStart:blue");
});
},
onPanUpdate: (details) {
setState(() {
bluePosition += details.delta;
print("blue is moved");
});
},
child: Container(
width: 100,
height: 100,
color: Colors.blue,
),
),
);
// Render the Stack so that the touched container is above.
return Stack(
children: redOnTop
? [blueContainer, redContainer] // Red on top.
: [redContainer, blueContainer], // Blue on top.
);
}
}
本文标签: flutterGestureDetector causes move of the wrong item in stackStack Overflow
版权声明:本文标题:flutter - GestureDetector causes move of the wrong item in stack - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741301642a2371122.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论