Flutter Flow widget Example

Last updated Mar 03, 2021

In this post we are going to learn about flow widget and its usage. If we need to create an animation that transforms the position of the children then we can use the flow widget.

Flow is a widget which arranges its child widgets based on FlowDelegate

 

Constructor

Flow({
  Key key,
  @required this.delegate,
  List<Widget> children = const <Widget>[],
}) 

 

To use Flow widget we need to pass FlowDelegate, which will control the appearance of the child widgets.

 

Create FlowDelegate

To create  FlowDelegate instance , we need to create a custom class which extends FlowDelegate.

 

This FlowDelegate contains below methods:

  • Constructor with super() call  super(repaint: )
  • void paintChildren(FlowPaintingContext context)
  • bool shouldRepaint(FlowExampleDelegate oldDelegate)
  • BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints)
  • Size getSize(BoxConstraints constraints)

 

 

void paintChildren(FlowPaintingContext context)

FlowPaintingContext itself has some properties and methods.

  • Size get size: The size of the container in which the children can be painted.
  • int get childCount: The number of children available to paint.
  • Size? getChildSize(int i): The size of the ith child.
  • void paintChild(int i, { Matrix4 transform, double opacity = 1.0 }): Used to paint the ith child

 

Size getSize(BoxConstraints constraints)

By default implementation of FlowDelegate's getSize method returns the biggest size that satisfies the constraints

Size getSize(BoxConstraints constraints) => constraints.biggest;

 

We can also set the required size for the child items by

Size getSize(BoxConstraints constraints) {

  return Size(70.0, double.infinity);

}

 

 

BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints)

By default, the children will use the given size constraints. That's because the default implementation of getConstraintsForChild method returns the given constraints

We can set the customize contraints by

 

BoxConstraints getConstraintsForChild(int i, BoxConstraints constraints) {

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

}

 

 

Complete example of Flow widget

import 'package:flutter/material.dart';

import 'package:flutter/widgets.dart';



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



class MyApp extends StatelessWidget {



  @override

  Widget build(BuildContext context) {

    return MaterialApp(

      title: 'rrtutors.com Flutter Tutorial',

      home: Scaffold(

        appBar: AppBar(

          title: const Text('Flow Widget Example'),

          backgroundColor: Colors.pink,

        ),

        body: FlowExample(),

      ),

    );

  }

}



class FlowExample extends StatefulWidget {



  @override

  _FlowExampleState createState() => _FlowExampleState();

}



class _FlowExampleState extends State<FlowExample>

    with SingleTickerProviderStateMixin {



  AnimationController _myAnimation;



  final List<IconData> _icons = <IconData>[

    Icons.menu,

    Icons.email,

    Icons.new_releases,

    Icons.notifications,

    Icons.bluetooth,

    Icons.wifi,

  ];



  @override

  void initState() {

    super.initState();



    _myAnimation = AnimationController(

      duration: const Duration(milliseconds: 500),

      vsync: this,

    );

  }



  Widget _buildItem(IconData icon) {

    return Padding(

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

      child: RawMaterialButton(

        fillColor: Colors.pinkAccent,

        splashColor: Colors.grey,

        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 Stack(

      children: [

        Container(color: Colors.grey),

        Flow(

          delegate: FlowExampleDelegate(myAnimation: _myAnimation),

          children: _icons

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

              .toList(),

        ),

      ],

    );

  }

}



class FlowExampleDelegate extends FlowDelegate {



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



  final Animation<double> myAnimation;



  // Put overridden methods here

  @override

  bool shouldRepaint(FlowExampleDelegate 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));

  }

}

 

 

 

Article Contributed By :
https://www.rrtutors.com/site_assets/profile/assets/img/avataaars.svg

2115 Views