Animating widget positions as the screen scrolls in flutter (GIF included)Flutter Layout: How can I put a Row inside a Flex (or another Row) in Flutter? Also using Stack widgetflutter : gif animation listener in ImageAbsolute position of Flutter widgetsAnimate ListView item to full screen in FlutterAnimating widgets positions while scrollingFlutter : Bad state: Stream has already been listened toPositioned Widget Animation with FlutterFlutter - Include Widget on Conditionanimate show or hide widgets with flutterHow to animate expandable Flutter widget to slide it out of the screen

Is it possible to put a rectangle as background in the author section?

Aragorn's "guise" in the Orthanc Stone

Did arcade monitors have same pixel aspect ratio as TV sets?

WiFi Thermostat, No C Terminal on Furnace

Pre-mixing cryogenic fuels and using only one fuel tank

Drawing ramified coverings with tikz

How do you make your own symbol when Detexify fails?

When were female captains banned from Starfleet?

What is this cable/device?

Which one is correct as adjective “protruding” or “protruded”?

Yosemite Fire Rings - What to Expect?

How to bake one texture for one mesh with multiple textures blender 2.8

How could a planet have erratic days?

What was this official D&D 3.5e Lovecraft-flavored rulebook?

Travelling outside the UK without a passport

Is there a name for this algorithm to calculate the concentration of a mixture of two solutions containing the same solute?

Longest common substring in linear time

Electoral considerations aside, what are potential benefits, for the US, of policy changes proposed by the tweet recognizing Golan annexation?

A social experiment. What is the worst that can happen?

On a tidally locked planet, would time be quantized?

Why electric field inside a cavity of a non-conducting sphere not zero?

What does routing an IP address mean?

Does a 'pending' US visa application constitute a denial?

Can I sign legal documents with a smiley face?



Animating widget positions as the screen scrolls in flutter (GIF included)


Flutter Layout: How can I put a Row inside a Flex (or another Row) in Flutter? Also using Stack widgetflutter : gif animation listener in ImageAbsolute position of Flutter widgetsAnimate ListView item to full screen in FlutterAnimating widgets positions while scrollingFlutter : Bad state: Stream has already been listened toPositioned Widget Animation with FlutterFlutter - Include Widget on Conditionanimate show or hide widgets with flutterHow to animate expandable Flutter widget to slide it out of the screen













0















I am trying to animate two Rows of widgets to collapse into 1 Row of these widgets as one scrolls. I am trying to achieve this behavior inside a SliverAppBar.



For clarification I have included a GIF here for reference. I would like the behavior you see in the app bar, but instead of 1 row to 2, i would like 2 row becoming 1.



https://media.giphy.com/media/2A4CP65QjamZC3K4c8/giphy.gif



Here is a quick snippet of what I have so far. I wrapped 2 Row widgets that contain 3 shrinkableBox widgets each into a Wrap widget. I dynamically adjust the size of these boxes by hooking into _scrollController.offset and doing some calculations. The rows do move around dynamically but they dont animate and move abruptly instead.



 double kExpandedHeight = 300.0;


Widget build(BuildContext context) {
double size = !_scrollController.hasClients || _scrollController.offset == 0 ? 75.0 : 75 - math.min(45.0, (45 / kExpandedHeight * math.min(_scrollController.offset, kExpandedHeight) * 1.5));
return Scaffold(
body: CustomScrollView(
controller: _scrollController,
slivers: <Widget>[
SliverAppBar(
pinned: true,
expandedHeight: kExpandedHeight,

title: new Text(
"Title!",
),
bottom: PreferredSize(child: Wrap(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ShrinkableBox(
onClick: ()
print("tapped");
,
size: size,
),
ShrinkableBox(
onClick: ()
print("tapped");
,
size: size,
),
ShrinkableBox(
onClick: ()
print("tapped");
,
size: size,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,

children: <Widget>[
ShrinkableBox(
onClick: ()
print("tapped");
,
size: size,
),
ShrinkableBox(
onClick: ()
print("tapped");
,
size: size,
),
ShrinkableBox(
onClick: ()
print("tapped");
,
size: size,
),
],
),
],
), preferredSize: new Size.fromHeight(55),),
)...
...Other sliver list content here...
...









share|improve this question


























    0















    I am trying to animate two Rows of widgets to collapse into 1 Row of these widgets as one scrolls. I am trying to achieve this behavior inside a SliverAppBar.



    For clarification I have included a GIF here for reference. I would like the behavior you see in the app bar, but instead of 1 row to 2, i would like 2 row becoming 1.



    https://media.giphy.com/media/2A4CP65QjamZC3K4c8/giphy.gif



    Here is a quick snippet of what I have so far. I wrapped 2 Row widgets that contain 3 shrinkableBox widgets each into a Wrap widget. I dynamically adjust the size of these boxes by hooking into _scrollController.offset and doing some calculations. The rows do move around dynamically but they dont animate and move abruptly instead.



     double kExpandedHeight = 300.0;


    Widget build(BuildContext context) {
    double size = !_scrollController.hasClients || _scrollController.offset == 0 ? 75.0 : 75 - math.min(45.0, (45 / kExpandedHeight * math.min(_scrollController.offset, kExpandedHeight) * 1.5));
    return Scaffold(
    body: CustomScrollView(
    controller: _scrollController,
    slivers: <Widget>[
    SliverAppBar(
    pinned: true,
    expandedHeight: kExpandedHeight,

    title: new Text(
    "Title!",
    ),
    bottom: PreferredSize(child: Wrap(
    children: <Widget>[
    Row(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    children: <Widget>[
    ShrinkableBox(
    onClick: ()
    print("tapped");
    ,
    size: size,
    ),
    ShrinkableBox(
    onClick: ()
    print("tapped");
    ,
    size: size,
    ),
    ShrinkableBox(
    onClick: ()
    print("tapped");
    ,
    size: size,
    ),
    Row(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,

    children: <Widget>[
    ShrinkableBox(
    onClick: ()
    print("tapped");
    ,
    size: size,
    ),
    ShrinkableBox(
    onClick: ()
    print("tapped");
    ,
    size: size,
    ),
    ShrinkableBox(
    onClick: ()
    print("tapped");
    ,
    size: size,
    ),
    ],
    ),
    ],
    ), preferredSize: new Size.fromHeight(55),),
    )...
    ...Other sliver list content here...
    ...









    share|improve this question
























      0












      0








      0








      I am trying to animate two Rows of widgets to collapse into 1 Row of these widgets as one scrolls. I am trying to achieve this behavior inside a SliverAppBar.



      For clarification I have included a GIF here for reference. I would like the behavior you see in the app bar, but instead of 1 row to 2, i would like 2 row becoming 1.



      https://media.giphy.com/media/2A4CP65QjamZC3K4c8/giphy.gif



      Here is a quick snippet of what I have so far. I wrapped 2 Row widgets that contain 3 shrinkableBox widgets each into a Wrap widget. I dynamically adjust the size of these boxes by hooking into _scrollController.offset and doing some calculations. The rows do move around dynamically but they dont animate and move abruptly instead.



       double kExpandedHeight = 300.0;


      Widget build(BuildContext context) {
      double size = !_scrollController.hasClients || _scrollController.offset == 0 ? 75.0 : 75 - math.min(45.0, (45 / kExpandedHeight * math.min(_scrollController.offset, kExpandedHeight) * 1.5));
      return Scaffold(
      body: CustomScrollView(
      controller: _scrollController,
      slivers: <Widget>[
      SliverAppBar(
      pinned: true,
      expandedHeight: kExpandedHeight,

      title: new Text(
      "Title!",
      ),
      bottom: PreferredSize(child: Wrap(
      children: <Widget>[
      Row(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      Row(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,

      children: <Widget>[
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ],
      ),
      ],
      ), preferredSize: new Size.fromHeight(55),),
      )...
      ...Other sliver list content here...
      ...









      share|improve this question














      I am trying to animate two Rows of widgets to collapse into 1 Row of these widgets as one scrolls. I am trying to achieve this behavior inside a SliverAppBar.



      For clarification I have included a GIF here for reference. I would like the behavior you see in the app bar, but instead of 1 row to 2, i would like 2 row becoming 1.



      https://media.giphy.com/media/2A4CP65QjamZC3K4c8/giphy.gif



      Here is a quick snippet of what I have so far. I wrapped 2 Row widgets that contain 3 shrinkableBox widgets each into a Wrap widget. I dynamically adjust the size of these boxes by hooking into _scrollController.offset and doing some calculations. The rows do move around dynamically but they dont animate and move abruptly instead.



       double kExpandedHeight = 300.0;


      Widget build(BuildContext context) {
      double size = !_scrollController.hasClients || _scrollController.offset == 0 ? 75.0 : 75 - math.min(45.0, (45 / kExpandedHeight * math.min(_scrollController.offset, kExpandedHeight) * 1.5));
      return Scaffold(
      body: CustomScrollView(
      controller: _scrollController,
      slivers: <Widget>[
      SliverAppBar(
      pinned: true,
      expandedHeight: kExpandedHeight,

      title: new Text(
      "Title!",
      ),
      bottom: PreferredSize(child: Wrap(
      children: <Widget>[
      Row(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      Row(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,

      children: <Widget>[
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ShrinkableBox(
      onClick: ()
      print("tapped");
      ,
      size: size,
      ),
      ],
      ),
      ],
      ), preferredSize: new Size.fromHeight(55),),
      )...
      ...Other sliver list content here...
      ...






      user-interface animation flutter






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 8 at 4:26









      smblsmbl

      587




      587






















          1 Answer
          1






          active

          oldest

          votes


















          1














          You could use a Stack together with Positioned widgets to position the ShrinkableBoxes as you need. Since what controls the animation is the scroll offset, you don't need to use animated widgets or an animation controller or something like it. Here's a working example which calculates the positions by linearly interpolating the initial and final position of the boxes (you can get different animation paths by changing the Curves.linear to other curves):



          import 'dart:math' as math;
          import 'dart:ui';

          import 'package:flutter/material.dart';

          void main()
          runApp(MaterialApp(home: Home()));


          class Home extends StatefulWidget
          @override
          State createState() => HomeState();


          class HomeState extends State<Home>
          static const double kExpandedHeight = 300.0;

          static const double kInitialSize = 75.0;

          static const double kFinalSize = 30.0;

          static const List<Color> kBoxColors = [
          Colors.red,
          Colors.green,
          Colors.yellow,
          Colors.purple,
          Colors.orange,
          Colors.grey,
          ];

          ScrollController _scrollController = new ScrollController();

          @override
          void initState()
          _scrollController.addListener(()
          setState(() /* State being set is the Scroll Controller's offset */ );
          );


          @override
          void dispose()
          _scrollController.dispose();


          Widget build(BuildContext context)

          Widget buildAppBarBottom(double size)
          double t = (size - kInitialSize) / (kFinalSize - kInitialSize);

          const double initialContainerHeight = 2 * kInitialSize;
          const double finalContainerHeight = kFinalSize;

          return Container(
          height: lerpDouble(initialContainerHeight, finalContainerHeight, t),
          child: LayoutBuilder(
          builder: (context, constraints)
          List<Widget> stackChildren = [];
          for (int i = 0; i < 6; i++)
          Offset offset = getInterpolatedOffset(i, constraints, t);
          stackChildren.add(Positioned(
          left: offset.dx,
          top: offset.dy,
          child: buildSizedBox(size, kBoxColors[i]),
          ));


          return Stack(children: stackChildren);
          ,
          ),
          );


          Offset getInterpolatedOffset(int index, BoxConstraints constraints, double t)
          Curve curve = Curves.linear;
          double curveT = curve.transform(t);

          Offset a = getOffset(index, constraints, kInitialSize, 3);
          Offset b = getOffset(index, constraints, kFinalSize, 6);

          return Offset(
          lerpDouble(a.dx, b.dx, curveT),
          lerpDouble(a.dy, b.dy, curveT),
          );


          Offset getOffset(int index, BoxConstraints constraints, double size, int columns)
          int x = index % columns;
          int y = index ~/ columns;
          double horizontalMargin = (constraints.maxWidth - size * columns) / 2;

          return Offset(horizontalMargin + x * size, y * size);


          Widget buildSizedBox(double size, Color color)
          return Container(
          height: size,
          width: size,
          color: color,
          );







          share|improve this answer








          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.




















          • This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

            – smbl
            Mar 19 at 3:26











          • @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

            – Luis Fernando Trivelatto
            Mar 19 at 20:33











          Your Answer






          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "1"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader:
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          ,
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );













          draft saved

          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55056721%2fanimating-widget-positions-as-the-screen-scrolls-in-flutter-gif-included%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          1














          You could use a Stack together with Positioned widgets to position the ShrinkableBoxes as you need. Since what controls the animation is the scroll offset, you don't need to use animated widgets or an animation controller or something like it. Here's a working example which calculates the positions by linearly interpolating the initial and final position of the boxes (you can get different animation paths by changing the Curves.linear to other curves):



          import 'dart:math' as math;
          import 'dart:ui';

          import 'package:flutter/material.dart';

          void main()
          runApp(MaterialApp(home: Home()));


          class Home extends StatefulWidget
          @override
          State createState() => HomeState();


          class HomeState extends State<Home>
          static const double kExpandedHeight = 300.0;

          static const double kInitialSize = 75.0;

          static const double kFinalSize = 30.0;

          static const List<Color> kBoxColors = [
          Colors.red,
          Colors.green,
          Colors.yellow,
          Colors.purple,
          Colors.orange,
          Colors.grey,
          ];

          ScrollController _scrollController = new ScrollController();

          @override
          void initState()
          _scrollController.addListener(()
          setState(() /* State being set is the Scroll Controller's offset */ );
          );


          @override
          void dispose()
          _scrollController.dispose();


          Widget build(BuildContext context)

          Widget buildAppBarBottom(double size)
          double t = (size - kInitialSize) / (kFinalSize - kInitialSize);

          const double initialContainerHeight = 2 * kInitialSize;
          const double finalContainerHeight = kFinalSize;

          return Container(
          height: lerpDouble(initialContainerHeight, finalContainerHeight, t),
          child: LayoutBuilder(
          builder: (context, constraints)
          List<Widget> stackChildren = [];
          for (int i = 0; i < 6; i++)
          Offset offset = getInterpolatedOffset(i, constraints, t);
          stackChildren.add(Positioned(
          left: offset.dx,
          top: offset.dy,
          child: buildSizedBox(size, kBoxColors[i]),
          ));


          return Stack(children: stackChildren);
          ,
          ),
          );


          Offset getInterpolatedOffset(int index, BoxConstraints constraints, double t)
          Curve curve = Curves.linear;
          double curveT = curve.transform(t);

          Offset a = getOffset(index, constraints, kInitialSize, 3);
          Offset b = getOffset(index, constraints, kFinalSize, 6);

          return Offset(
          lerpDouble(a.dx, b.dx, curveT),
          lerpDouble(a.dy, b.dy, curveT),
          );


          Offset getOffset(int index, BoxConstraints constraints, double size, int columns)
          int x = index % columns;
          int y = index ~/ columns;
          double horizontalMargin = (constraints.maxWidth - size * columns) / 2;

          return Offset(horizontalMargin + x * size, y * size);


          Widget buildSizedBox(double size, Color color)
          return Container(
          height: size,
          width: size,
          color: color,
          );







          share|improve this answer








          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.




















          • This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

            – smbl
            Mar 19 at 3:26











          • @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

            – Luis Fernando Trivelatto
            Mar 19 at 20:33
















          1














          You could use a Stack together with Positioned widgets to position the ShrinkableBoxes as you need. Since what controls the animation is the scroll offset, you don't need to use animated widgets or an animation controller or something like it. Here's a working example which calculates the positions by linearly interpolating the initial and final position of the boxes (you can get different animation paths by changing the Curves.linear to other curves):



          import 'dart:math' as math;
          import 'dart:ui';

          import 'package:flutter/material.dart';

          void main()
          runApp(MaterialApp(home: Home()));


          class Home extends StatefulWidget
          @override
          State createState() => HomeState();


          class HomeState extends State<Home>
          static const double kExpandedHeight = 300.0;

          static const double kInitialSize = 75.0;

          static const double kFinalSize = 30.0;

          static const List<Color> kBoxColors = [
          Colors.red,
          Colors.green,
          Colors.yellow,
          Colors.purple,
          Colors.orange,
          Colors.grey,
          ];

          ScrollController _scrollController = new ScrollController();

          @override
          void initState()
          _scrollController.addListener(()
          setState(() /* State being set is the Scroll Controller's offset */ );
          );


          @override
          void dispose()
          _scrollController.dispose();


          Widget build(BuildContext context)

          Widget buildAppBarBottom(double size)
          double t = (size - kInitialSize) / (kFinalSize - kInitialSize);

          const double initialContainerHeight = 2 * kInitialSize;
          const double finalContainerHeight = kFinalSize;

          return Container(
          height: lerpDouble(initialContainerHeight, finalContainerHeight, t),
          child: LayoutBuilder(
          builder: (context, constraints)
          List<Widget> stackChildren = [];
          for (int i = 0; i < 6; i++)
          Offset offset = getInterpolatedOffset(i, constraints, t);
          stackChildren.add(Positioned(
          left: offset.dx,
          top: offset.dy,
          child: buildSizedBox(size, kBoxColors[i]),
          ));


          return Stack(children: stackChildren);
          ,
          ),
          );


          Offset getInterpolatedOffset(int index, BoxConstraints constraints, double t)
          Curve curve = Curves.linear;
          double curveT = curve.transform(t);

          Offset a = getOffset(index, constraints, kInitialSize, 3);
          Offset b = getOffset(index, constraints, kFinalSize, 6);

          return Offset(
          lerpDouble(a.dx, b.dx, curveT),
          lerpDouble(a.dy, b.dy, curveT),
          );


          Offset getOffset(int index, BoxConstraints constraints, double size, int columns)
          int x = index % columns;
          int y = index ~/ columns;
          double horizontalMargin = (constraints.maxWidth - size * columns) / 2;

          return Offset(horizontalMargin + x * size, y * size);


          Widget buildSizedBox(double size, Color color)
          return Container(
          height: size,
          width: size,
          color: color,
          );







          share|improve this answer








          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.




















          • This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

            – smbl
            Mar 19 at 3:26











          • @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

            – Luis Fernando Trivelatto
            Mar 19 at 20:33














          1












          1








          1







          You could use a Stack together with Positioned widgets to position the ShrinkableBoxes as you need. Since what controls the animation is the scroll offset, you don't need to use animated widgets or an animation controller or something like it. Here's a working example which calculates the positions by linearly interpolating the initial and final position of the boxes (you can get different animation paths by changing the Curves.linear to other curves):



          import 'dart:math' as math;
          import 'dart:ui';

          import 'package:flutter/material.dart';

          void main()
          runApp(MaterialApp(home: Home()));


          class Home extends StatefulWidget
          @override
          State createState() => HomeState();


          class HomeState extends State<Home>
          static const double kExpandedHeight = 300.0;

          static const double kInitialSize = 75.0;

          static const double kFinalSize = 30.0;

          static const List<Color> kBoxColors = [
          Colors.red,
          Colors.green,
          Colors.yellow,
          Colors.purple,
          Colors.orange,
          Colors.grey,
          ];

          ScrollController _scrollController = new ScrollController();

          @override
          void initState()
          _scrollController.addListener(()
          setState(() /* State being set is the Scroll Controller's offset */ );
          );


          @override
          void dispose()
          _scrollController.dispose();


          Widget build(BuildContext context)

          Widget buildAppBarBottom(double size)
          double t = (size - kInitialSize) / (kFinalSize - kInitialSize);

          const double initialContainerHeight = 2 * kInitialSize;
          const double finalContainerHeight = kFinalSize;

          return Container(
          height: lerpDouble(initialContainerHeight, finalContainerHeight, t),
          child: LayoutBuilder(
          builder: (context, constraints)
          List<Widget> stackChildren = [];
          for (int i = 0; i < 6; i++)
          Offset offset = getInterpolatedOffset(i, constraints, t);
          stackChildren.add(Positioned(
          left: offset.dx,
          top: offset.dy,
          child: buildSizedBox(size, kBoxColors[i]),
          ));


          return Stack(children: stackChildren);
          ,
          ),
          );


          Offset getInterpolatedOffset(int index, BoxConstraints constraints, double t)
          Curve curve = Curves.linear;
          double curveT = curve.transform(t);

          Offset a = getOffset(index, constraints, kInitialSize, 3);
          Offset b = getOffset(index, constraints, kFinalSize, 6);

          return Offset(
          lerpDouble(a.dx, b.dx, curveT),
          lerpDouble(a.dy, b.dy, curveT),
          );


          Offset getOffset(int index, BoxConstraints constraints, double size, int columns)
          int x = index % columns;
          int y = index ~/ columns;
          double horizontalMargin = (constraints.maxWidth - size * columns) / 2;

          return Offset(horizontalMargin + x * size, y * size);


          Widget buildSizedBox(double size, Color color)
          return Container(
          height: size,
          width: size,
          color: color,
          );







          share|improve this answer








          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.










          You could use a Stack together with Positioned widgets to position the ShrinkableBoxes as you need. Since what controls the animation is the scroll offset, you don't need to use animated widgets or an animation controller or something like it. Here's a working example which calculates the positions by linearly interpolating the initial and final position of the boxes (you can get different animation paths by changing the Curves.linear to other curves):



          import 'dart:math' as math;
          import 'dart:ui';

          import 'package:flutter/material.dart';

          void main()
          runApp(MaterialApp(home: Home()));


          class Home extends StatefulWidget
          @override
          State createState() => HomeState();


          class HomeState extends State<Home>
          static const double kExpandedHeight = 300.0;

          static const double kInitialSize = 75.0;

          static const double kFinalSize = 30.0;

          static const List<Color> kBoxColors = [
          Colors.red,
          Colors.green,
          Colors.yellow,
          Colors.purple,
          Colors.orange,
          Colors.grey,
          ];

          ScrollController _scrollController = new ScrollController();

          @override
          void initState()
          _scrollController.addListener(()
          setState(() /* State being set is the Scroll Controller's offset */ );
          );


          @override
          void dispose()
          _scrollController.dispose();


          Widget build(BuildContext context)

          Widget buildAppBarBottom(double size)
          double t = (size - kInitialSize) / (kFinalSize - kInitialSize);

          const double initialContainerHeight = 2 * kInitialSize;
          const double finalContainerHeight = kFinalSize;

          return Container(
          height: lerpDouble(initialContainerHeight, finalContainerHeight, t),
          child: LayoutBuilder(
          builder: (context, constraints)
          List<Widget> stackChildren = [];
          for (int i = 0; i < 6; i++)
          Offset offset = getInterpolatedOffset(i, constraints, t);
          stackChildren.add(Positioned(
          left: offset.dx,
          top: offset.dy,
          child: buildSizedBox(size, kBoxColors[i]),
          ));


          return Stack(children: stackChildren);
          ,
          ),
          );


          Offset getInterpolatedOffset(int index, BoxConstraints constraints, double t)
          Curve curve = Curves.linear;
          double curveT = curve.transform(t);

          Offset a = getOffset(index, constraints, kInitialSize, 3);
          Offset b = getOffset(index, constraints, kFinalSize, 6);

          return Offset(
          lerpDouble(a.dx, b.dx, curveT),
          lerpDouble(a.dy, b.dy, curveT),
          );


          Offset getOffset(int index, BoxConstraints constraints, double size, int columns)
          int x = index % columns;
          int y = index ~/ columns;
          double horizontalMargin = (constraints.maxWidth - size * columns) / 2;

          return Offset(horizontalMargin + x * size, y * size);


          Widget buildSizedBox(double size, Color color)
          return Container(
          height: size,
          width: size,
          color: color,
          );








          share|improve this answer








          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          share|improve this answer



          share|improve this answer






          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.









          answered Mar 18 at 8:06









          Luis Fernando TrivelattoLuis Fernando Trivelatto

          262




          262




          New contributor




          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.





          New contributor





          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.






          Luis Fernando Trivelatto is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.












          • This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

            – smbl
            Mar 19 at 3:26











          • @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

            – Luis Fernando Trivelatto
            Mar 19 at 20:33


















          • This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

            – smbl
            Mar 19 at 3:26











          • @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

            – Luis Fernando Trivelatto
            Mar 19 at 20:33

















          This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

          – smbl
          Mar 19 at 3:26





          This is exactly what i wanted! How were you able to figure this out? This is a pretty complex piece of code. I would like to learn animations like this for myself as well.

          – smbl
          Mar 19 at 3:26













          @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

          – Luis Fernando Trivelatto
          Mar 19 at 20:33






          @smbl Thanks! I guess I've had a fair share of struggles with animations in Flutter hehe. Have you checked out the Animations section of the Flutter website? While it explains how to do more complex animations, you might also want to check out the implicitly animated widgets, which are still powerful and simpler to use, such as AnimatedContainer: flutter.dev/docs/development/ui/widgets/animation

          – Luis Fernando Trivelatto
          Mar 19 at 20:33




















          draft saved

          draft discarded
















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid


          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.

          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55056721%2fanimating-widget-positions-as-the-screen-scrolls-in-flutter-gif-included%23new-answer', 'question_page');

          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Identity Server 4 is not redirecting to Angular app after login2019 Community Moderator ElectionIdentity Server 4 and dockerIdentityserver implicit flow unauthorized_clientIdentityServer Hybrid Flow - Access Token is null after user successful loginIdentity Server to MVC client : Page Redirect After loginLogin with Steam OpenId(oidc-client-js)Identity Server 4+.NET Core 2.0 + IdentityIdentityServer4 post-login redirect not working in Edge browserCall to IdentityServer4 generates System.NullReferenceException: Object reference not set to an instance of an objectIdentityServer4 without HTTPS not workingHow to get Authorization code from identity server without login form

          2005 Ahvaz unrest Contents Background Causes Casualties Aftermath See also References Navigation menue"At Least 10 Are Killed by Bombs in Iran""Iran"Archived"Arab-Iranians in Iran to make April 15 'Day of Fury'"State of Mind, State of Order: Reactions to Ethnic Unrest in the Islamic Republic of Iran.10.1111/j.1754-9469.2008.00028.x"Iran hangs Arab separatists"Iran Overview from ArchivedConstitution of the Islamic Republic of Iran"Tehran puzzled by forged 'riots' letter""Iran and its minorities: Down in the second class""Iran: Handling Of Ahvaz Unrest Could End With Televised Confessions""Bombings Rock Iran Ahead of Election""Five die in Iran ethnic clashes""Iran: Need for restraint as anniversary of unrest in Khuzestan approaches"Archived"Iranian Sunni protesters killed in clashes with security forces"Archived

          Can't initialize raids on a new ASUS Prime B360M-A motherboard2019 Community Moderator ElectionSimilar to RAID config yet more like mirroring solution?Can't get motherboard serial numberWhy does the BIOS entry point start with a WBINVD instruction?UEFI performance Asus Maximus V Extreme