Advanced Flutter Layout — Flow

Flutter provide a wide range of widgets to customize your layout, most of which can be found here. However if you are like me and you don’t want to miss anything related to flutter you probably have seen a few interesting widget names. In this article I will be talking about one of these widgets,the flow widget.

What the Flow Widget is NOT?

This is just a quick note before we get started if you have a Java background you may have heard of the flow layout which usually arranges components in an LRT/RTL flow, much like lines of text in a paragraph. In flutter, this is done using the Wrap widget leaving flow to serve a different purpose when it comes to layout in Flutter.

this is not the flow layout in flutter

Simple Flow Example

Let’s first start with the simplest example of the Flow widget. Once we have a basic understanding, we will look at it in greater detail and play a little more with it:

The buildItem method return a simple circle with the number passed as an argument

Now SampleFlowDelegate is where all the fun happens

Run this piece of code and you will see just one item on the screen. This on-screen item is actually the last item. At this point, you might be thinking that the Flow widget operates similar to Stack. In someways, yes, they do have a few similar aspects such as the order in which the widgets are drawn. This is the reason we are only able to see the last item in our example.


So Why the Flow Layout

One good reason for using flow is it is optimized for transformation matrices, allowing you to do many kinds of crazy transformation without fear of losing performance. This is the key difference from the Stack widget. Unlike Stack which does all positioning and sizing during the layout phase, with Flow,we can avoid the build phase (I will talk about that later).

This is a simple example I made while I was experimenting with this widget


Practical example

Let’s try to make this layout where you can stack children on top of each other and when you double click on one of them it will expand:

Step 1: Stack children gradually

To achieve this, we need to get the size of the current child. We can easily do this using context.getChildSize(i). Now, we multiply the height by 0.1 to get that nice effect. You can change the value to 0.5 or 0.9 to see how they layout will look.

Step 2: Animate the children

And here the power of the Flow layout shines because of the FlowDelegate accepts an optional repaint arguments of type Listenable. This listenable will reprint the Flow whenever the listeners are notified.

Step 3: Create the animation

There is nothing special here and I will link the full source code at the end of this article so you will see all the boilerplate:

Step 4: Animate on Tap / DoubleTap

Just wrap the item in buildItem method with a GestureDetector and set onTap and onDoubleTap like this

And the final step is to pass the animation to the delegate delegate: SampleFlowDelegate(openAnimation: openAnimation)


Performance comparison

As some of you might know, we only have 16 ms to draw each frame. If we take longer than 16 ms, our app will being to drop frames, causing the UI to stutter resulting in a poor user experience. For modern devices, this is not a problem however for lower end devices try to render complex animations might be difficult. Since flow delegate repaint when the animation ticks,we save a few milliseconds.

Below is a comparison is using the previous example:

1) SetState to build when the animation ticks

2) Repaint when the animation ticks

And as you can see we eliminated the build phase completely here


Conclusion

So to wrap up, Flow doesn't give you anything that you can’t get with “normal” widgets however, when it comes to animations and re-positioning widgets using translations, it does provide optimal performance.

If you’d like to give it a try check out this simple code from the example show in earlier.