Hackernoon logoHow to Create Custom Layout Widgets in Flutter by@sayonetech

How to Create Custom Layout Widgets in Flutter

SayOne Technologies Hacker Noon profile picture

SayOne Technologies

This blog assumes that you have a beginner’s knowledge in Flutter. Otherwise, dive into to get the basics and come right back!

Now, how do we layout widgets in Flutter? Normally we use a stack, row or column. But what if our requirement is more than that? If we want to arrange some widgets horizontally, we use a Row Widget. If we want to arrange them vertically, we would wrap them in a Column and use Stack to arrange elements on top of another. But we can’t expect our UI to be so simple as that. For example, I was met with a requirement of a circular widget with five equally spaced buttons located on it (check out the image below!).

Don’t worry! We can do it with a CustomMultiChildLayout widget which takes only two arguments.

delegate: _CircularLayoutDelegate(
itemCount: 5,
Radius: 150.0,
children: products,
  1. delegate — of type MultiChildLayoutDelegate which is responsible for positioning the children.
  2. children — which is the array of widgets to be positioned. The children argument is similar to the one used in rows and columns, but one difference is that every item in that array should be marked with a Layout id for identifying that child.
for (int i = 0; i < 5; i++) {
products.add( LayoutId(
id: ‘BUTTON$i’,
child: item,

Now, the important part is the delegate. The MultiChildLayoutDelegate is an abstract class. So, we have to extend it for our use. Override the method performLayout and we can write the code to position items in it.

class _CircularLayoutDelegate extends MultiChildLayoutDelegate {
static const String actionButton = 'BUTTON';
Offset center;
final int itemCount;
final double radius;

@required this.itemCount,
@required this.radius,

void performLayout(Size size) {
center = Offset(size.width / 2, size.height / 2);
for (int i = 0; i < itemCount; i++) {
final String actionButtonId = '$actionButton$i';

if (hasChild(actionButtonId)) {
final Size buttonSize =
layoutChild(actionButtonId, BoxConstraints.loose(size));
final double itemAngle = _calculateItemAngle(i);

(center.dx - buttonSize.width / 2) + (radius) * Math.cos(itemAngle),
(center.dy - buttonSize.height / 2) +
(radius) * Math.sin(itemAngle),

bool shouldRelayout(_CircularLayoutDelegate oldDelegate) =>
itemCount != oldDelegate.itemCount ||
radius != oldDelegate.radius ;
  1. The performLayout method gives us the widget’s size from which we can calculate the center of the circle.
  2. Since we have to layout five widgets along the circle, use a for loop for it.
  3. Remember we have created every item with an id attached to it. So we are using the same id to check whether the item exists or not.
  4. Now, size of the button is retrieved using layoutChild method.
  5. The angle between the item and center axis is calculated using the function _calculateItemAngle.
const double _radiansPerDegree = Math.pi / 180;
final double _startAngle = -90.0 * _radiansPerDegree;
double _itemSpacing = 360.0 / 5.0;
double _calculateItemAngle(int index) {
return _startAngle + index * _itemSpacing * _radiansPerDegree;

6. Finally, positionChild method is called with the id of the item and the offset. The offset is calculated using the mathematical equation,

A point at angle theta on the circle whose centre is (x0,y0) and whose radius is r is (x0 + r cos theta, y0 + r sin theta).

7. The shouldRelayout method is called to compare the current layout and the old one and return true if a relayout is needed.

So, that’s how easy it is to create custom layouts in Flutter. If you want to read more about our Flutter experience, check out our recent blog. Flutter has always been our core areas of expertise. So, stay tuned for more similar updates and information exchange!

You can further learn about our Flutter contributions in GitHub.

Originally published at https://www.sayonetech.com/blog/how-create-custom-layout-widgets-flutter/.


Join Hacker Noon

Create your free account to unlock your custom reading experience.