This is similar to an old issue from the old issue tracker. This new issue surfaced because of that old issue's fix (c44dd17). When child.parentData = null; is removed again, then we no longer see this new issue's behavior (though we do see the old one's).
Anyway, the example is 2 stacks that can be tapped to move up or down on the screen. Notably, the lower part of the screen will also wrap the Stack in a Listener, which causes problems when a Disk widget is moved from the bottom stack back to the top stack.
This is lib/main.dart.
import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
class Disk extends StatefulComponent {
String name;
Function cb;
Disk(String name, bool useKey, this.cb) :
super(key: useKey ? new GlobalObjectKey(name) : null),
name = name;
DiskState createState() => new DiskState();
}
class DiskState extends State<Disk> {
Point _oldLocation;
@override
void initState() {
print("init ${config.name}");
super.initState();
_checkPosition();
}
void _checkPosition() {
scheduler.requestPostFrameCallback((Duration d) {
print("Post Frame Callback of ${config.name} ${d}");
Point newLocation = getGlobalPosition();
print("Moved from ${_oldLocation} to ${newLocation}");
setState(() {
_oldLocation = newLocation;
});
});
}
@override
void didUpdateConfig(Disk oldConfig) {
print("Update ${oldConfig.name} to ${config.name}");
_checkPosition();
}
Point getGlobalPosition() {
RenderBox box = context.findRenderObject();
return box.localToGlobal(Point.origin);
}
Widget build(BuildContext context) {
return new InkWell(
onTap: config.cb,
child: new Container(
decoration: new BoxDecoration(backgroundColor: Colors.blue[500]),
width: 30.0,
height: 30.0,
child: new Text(config.name)
)
);
}
}
class Holder extends StatefulComponent {
HolderState createState() => new HolderState();
}
class HolderState extends State<Holder> {
Map<String, bool> data = new Map<String, bool>();
void initState() {
super.initState();
data["a"] = true;
data["b"] = true;
}
Function _makeChangeDataCb(String name) {
return () {
setState(() {
data[name] = !data[name];
});
};
}
Widget build(BuildContext context) {
// Note1: Set to false to see the effect go away. Set to true, to see the shifted effect in printouts.
bool useKey = true;
List<Widget> trueKids = new List<Widget>();
List<Widget> falseKids = new List<Widget>();
data.forEach((String name, bool isTop) {
Disk disk = new Disk(name, useKey, _makeChangeDataCb(name));
Widget k = disk;
// Note2: If you add "|| true", then the effect disappears. The widget tree must misalign for the effect to occur.
if (!isTop) {
// Note3: This listener gets in the way of the position computation and makes the transform occur twice during localToGlobal. But only when there is a key.
k = new Listener(
child: disk
);
}
Widget kid = new Positioned(
top: 5.0,
left: 5.0,
child: k
);
if (isTop) {
trueKids.add(kid);
} else {
falseKids.add(kid);
}
});
return new Column([
new Container(
decoration: new BoxDecoration(backgroundColor: Colors.red[500]),
child: new Stack(trueKids),
width: 60.0,
height: 60.0
),
new Container(
decoration: new BoxDecoration(backgroundColor: Colors.red[500]),
child: new Stack(falseKids),
width: 60.0,
height: 60.0
),
new FlatButton(child: new Text("Debug"), onPressed: debugDumpApp)
]);
}
}
void main() {
runApp(new Holder());
}
You can use this pubspec.yaml and pub run sky_tools start
name: keyedWidgetsPosition
dependencies:
flutter: "0.0.18"
sky_tools: any
Or you can run the example with the new way of launching flutter apps.
This is similar to an old issue from the old issue tracker. This new issue surfaced because of that old issue's fix (c44dd17). When
child.parentData = null;is removed again, then we no longer see this new issue's behavior (though we do see the old one's).Anyway, the example is 2 stacks that can be tapped to move up or down on the screen. Notably, the lower part of the screen will also wrap the Stack in a Listener, which causes problems when a Disk widget is moved from the bottom stack back to the top stack.
This is
lib/main.dart.You can use this
pubspec.yamlandpub run sky_tools startOr you can run the example with the new way of launching flutter apps.