Skip to content

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

Closed

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

  1. changed the title [-]Update Widget is sized wrong (but placed correctly)[/-] [+]Updated Widget is sized wrong (but placed correctly)[/+] on Nov 12, 2015
  2. added
    c: regressionIt was better in the past than it is now
    frameworkflutter/packages/flutter repository. See also f: labels.
    on Nov 12, 2015
  3. self-assigned this
    on Nov 12, 2015
  4. abarth commented on Nov 13, 2015

    @abarth
    Contributor

    Reduction

    import 'package:flutter/material.dart';
    
    class NewHolder extends StatefulComponent {
      NewHolderState createState() => new NewHolderState();
    }
    
    class NewHolderState extends State<NewHolder> {
      GlobalKey key = new GlobalKey();
    
      bool nested = false;
    
      Widget build(BuildContext context) {
    
        Widget child = new Container(
          key: key,
          width: 100.0,
          height: 100.0,
          decoration: new BoxDecoration(backgroundColor: Colors.blue[500])
        );
    
        if (nested)
          child = new MetaData(child: child);
    
        return new Listener(
          onPointerDown: (_) {
            setState(() {
              nested = !nested;
            });
          },
          child: new Container(
            decoration: new BoxDecoration(backgroundColor: Colors.green[500]),
            child: new Stack([
              new Positioned(
                top: 50.0,
                left: 50.0,
                child: child
              )
            ])
          )
        );
      }
    }
    
    void main() {
      runApp(new NewHolder());
    }
  5. abarth commented on Nov 13, 2015

    @abarth
    Contributor

    I have a fix, need to write a test.

  6. afandria commented on Nov 13, 2015

    @afandria
    ContributorAuthor

    Great, thank you for fixing it so quickly!

  7. abarth commented on Nov 13, 2015

    @abarth
    Contributor

    Well, I haven't landed the fix yet. :)

  8. added a commit that references this issue on Nov 13, 2015
    35464f4
  9. github-actions commented on Sep 7, 2021

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  10. locked as resolved and limited conversation to collaborators on Sep 7, 2021
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