Sitelet https://github.com/flutter/flutter/issues/345
Skip to content

Updated Widget is sized wrong (but placed correctly) #345

Description

@afandria

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

c: regressionIt was better in the past than it is nowframeworkflutter/packages/flutter repository. See also f: labels.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions