Flow Widget In Flutter
By: Shaiq Khan
Tags: Flutter, Flow, Mobile App Development, Flutter App Development, Dart

Flow Widget:

Flow is a widget that sizes and positions its children proficiently as indicated by the rationale of a FlowDelegate. This widget is helpful when the children should be repositioned utilizing change matrices. For instance, if you need to make an animation that changes the situation of the children.

Demo Module :

The above demo video shows how to create a floating menu in a flutter. It shows how the floating menu that can expand/collapse using the Flow widget will work in your flutter applications. It shows when the code successfully runs, the user presses the menu button, then all icons will be expanded and the user press again, then all icons will collapse. It will be shown on your devices.

Constructor:

To utilize Flow, you need to call the constructor underneath:

Flow({

Key key,

@required this.delegate,

List<Widget> children = const <Widget>[],

})

To make an example of Flow, the only required contention is delegate. You need to pass a FlowDelegate which is capable to control the presence of the flow design.

Parameters:

There are some parameters of Flow are:

Key key : This parameter is used to control how a widget is replaced with another widget.

: This parameter is used to control how a widget is replaced with another widget. FlowDelegate delegate : This parameter is used by the delegate that controls the transformation matrices of the children.

: This parameter is used by the delegate that controls the transformation matrices of the children. List<Widget> children : This parameter is used to the widgets below this widget in the tree.

How to implement code in dart file :

You need to implement it in your code respectively:

Create a new dart file called flow_demo_delegate.dart inside the lib folder.

To make an instance of FlowDelegate, you need to make a custom class that expands FlowDelegate. The custom class needs to call the super constructor which is a const constructor. It has one boundary whose type is Listenable. It’s entirely expected to pass an example of Animation as the Listenable. Bypassing an Animation will pay attention to the animation and repaint at whatever point the animation ticks.

class FlowDemoDelegate extends FlowDelegate {



FlowDemoDelegate({this.myAnimation}) : super(repaint: myAnimation);



final Animation<double> myAnimation;

}

Other than calling the constructor, there are a few techniques you can supersede, two of them should be overridden since they don’t have a default execution. paintChild should be called for painting every child dependent on the given change grid. The principal boundary i is the record of the child to be painted. You can paint the children at any request, however, every child must be painted once. A child's situation relies upon the consequence of the holder’s arrange framework connected with the given change lattice. The upper left corner is set to be the beginning of the parent’s arrange framework. The value of x is expanding rightward, while the worth of y is expanding lower.

The size and childCount properties just as the getChildSize strategy may be valuable inside the FlowDelegate’s paintChildren technique. For instance, if you need to perform a loop dependent on the number of children or interpret the situation of a child dependent on its size.

import 'package:flutter/material.dart';



class FlowDemoDelegate extends FlowDelegate {



FlowDemoDelegate({this.myAnimation}) : super(repaint: myAnimation);



final Animation<double> myAnimation;



@override

bool shouldRepaint(FlowDemoDelegate oldDelegate) {

return myAnimation != oldDelegate.myAnimation;

}



@override

void paintChildren(FlowPaintingContext context) {

for (int i = context.childCount - 1; i >= 0; i--) {

double dx = (context.getChildSize(i).height + 10) * i;

context.paintChild(

i,

transform: Matrix4.translationValues(0, dx * myAnimation.value + 10, 0),

);

}

}



@override

Size getSize(BoxConstraints constraints) {

return Size(70.0, double.infinity);

}



@override

BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) {

return i == 0 ? constraints : BoxConstraints.tight(const Size(50.0, 50.0));

}

}

The other technique that you need to supersede is shouldRepaint. The bool return value of the strategy is utilized to decide if the children should be repainted. The technique has a boundary that will be passed with the old instance of the delegate. Along these lines, you can look at the fields of the past occurrence with the current fields to decide if repainting ought to be performed.

Having made the custom FlowDelegate class, presently we can call the constructor of Flow. For the delegate argument, pass an occurrence of FlowDemoDelegate. Since the constructor of FlowDemaoDelegate requires an occasion of Animation, we need to make an Animation.

Create a new dart file called main.dart inside the lib folder.

In the first, add with SingleTickerProviderStateMixin in the revelation of the state class. Thusly, it becomes conceivable to get the TickerProvider which is required when calling the constructor of AnimationController.

class _FlowDemoState extends State<FlowDemo>

with SingleTickerProviderStateMixin {



AnimationController _myAnimation;

...

}

Now, we will add List of IconData

final List<IconData> _icons = <IconData>[

Icons.menu,

Icons.email,

Icons.settings,

Icons.notifications,

Icons.person,

Icons.wifi,

];

We will create initState() method. In this method, we will add _myAnimation is equal to the AnimationController().

@override

void initState() {

super.initState();



_myAnimation = AnimationController(

duration: const Duration(seconds: 1),

vsync: this,

);

}

We will deeply define _buildItem widget are:

In this widget, we will return Padding(). Inside, add a RawMaterialButton() with fillColor, shape, BoxConstraints is tight and onPressed() function. In this function, we will add _myAnimation.status is qual to AnimationStatus.completed then show _myAnimation.reverse() else show a _myAnimation.forward(). Its child property, we will show a icon.

Widget _buildItem(IconData icon) {

return Padding(

padding: const EdgeInsets.symmetric(horizontal: 10.0),

child: RawMaterialButton(

fillColor: Colors.cyan,

shape: CircleBorder(),

constraints: BoxConstraints.tight(Size.square(50.0)),

onPressed: () {

_myAnimation.status == AnimationStatus.completed

? _myAnimation.reverse()

: _myAnimation.forward();

},

child: Icon(

icon,

color: Colors.white,

size: 30.0,

),

),

);

}

In the body, we will add to changing the size of the Flow widget, you may likewise have to change how the widget ought to be spread out comparative with different widgets. Generally, you can wrap it as the child of another widget. For instance, you can use the Align widget to set the alignment or use the Stack widget to make the button floating above different widgets.

Stack(

children: [

Container(color: Colors.grey[200]),

Flow(

delegate: FlowDemoDelegate(myAnimation: _myAnimation),

children: _icons

.map<Widget>((IconData icon) => _buildItem(icon))

.toList(),

),

],

),

When we run the application, we ought to get the screen’s output like the underneath screen capture.

Final Output

Code File:

import 'package:flutter/material.dart';

import 'package:flutter/widgets.dart';

import 'package:flutter_flow_demo/flow_demo_delegate.dart';

import 'package:flutter_flow_demo/splash_screen.dart';



void main() => runApp(MyApp());



class MyApp extends StatelessWidget {



@override

Widget build(BuildContext context) {

return MaterialApp(

debugShowCheckedModeBanner: false,

home: Splash(),

);

}

}



class FlowDemo extends StatefulWidget {



@override

_FlowDemoState createState() => _FlowDemoState();

}



class _FlowDemoState extends State<FlowDemo>

with SingleTickerProviderStateMixin {



AnimationController _myAnimation;



final List<IconData> _icons = <IconData>[

Icons.menu,

Icons.email,

Icons.settings,

Icons.notifications,

Icons.person,

Icons.wifi,

];



@override

void initState() {

super.initState();



_myAnimation = AnimationController(

duration: const Duration(seconds: 1),

vsync: this,

);

}



Widget _buildItem(IconData icon) {

return Padding(

padding: const EdgeInsets.symmetric(horizontal: 10.0),

child: RawMaterialButton(

fillColor: Colors.cyan,

shape: CircleBorder(),

constraints: BoxConstraints.tight(Size.square(50.0)),

onPressed: () {

_myAnimation.status == AnimationStatus.completed

? _myAnimation.reverse()

: _myAnimation.forward();

},

child: Icon(

icon,

color: Colors.white,

size: 30.0,

),

),

);

}



@override

Widget build(BuildContext context) {

return Scaffold(

appBar: AppBar(

automaticallyImplyLeading: false,

title: const Text('Flutter Flow Widget Demo'),

backgroundColor: Colors.cyan,

),

body: Stack(

children: [

Container(color: Colors.grey[200]),

Flow(

delegate: FlowDemoDelegate(myAnimation: _myAnimation),

children: _icons

.map<Widget>((IconData icon) => _buildItem(icon))

.toList(),

),

],

),

);

}

}

Conclusion:

In the article, I have explained the basic structure of the Flow Widget in a flutter; you can modify this code according to your choice. This was a small introduction to Flow Widget On User Interaction from my side, and it’s working using Flutter.

I hope this blog will provide you with sufficient information on Trying up the Flow Widget in your flutter projects. We will show you what the Flow Widget is?. Show a constructor and parameters of the Flow Widget. The Flow widget is appropriate when you need to make an animation that repositions the children. It can make the cycle more proficient because it just requirements to repaint at whatever point the animation ticks. Hence, the build and design periods of the pipeline can be kept away from. To utilize the Flow widget, you need to comprehend FlowDelegate since the rationale of how to paint the children generally should be characterized inside a class that extends FlowDelegate. So please try it.

❤ ❤ Thanks for reading this article ❤❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.