Search code examples
flutterflutter-animation

How to create Nested L shaped Widget in Flutter


I want to create the following L shaped design : -

enter image description here

This can be created using simple Column , Row and Expanded Widgets but I am not able to think it through. Design must be responsive as the Size of the Square changes. I thought about using Container Widget and its left and bottom Border in order to make the L shape but the issue with that is Container will be nested and hence might have to use stack but Expanded Widget wont work properly inside it.


Solution

  • Following is the minimum required code for the given design:

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
     const MyApp({super.key});
    
     @override
     Widget build(BuildContext context) {
      return MaterialApp(
       home: Scaffold(
        appBar: AppBar(
          title: const Text('LShaped Design'),
          backgroundColor: Colors.blue,
        ),
        body: SizedBox(
          height: double.maxFinite,
          width: double.maxFinite,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Stack(
                children: <Widget>[
                  Container(
                    width: 100,
                    height: 100,
                    decoration: BoxDecoration(
                      color: Colors.white60,
                      border: Border.all(color: Colors.black, style: BorderStyle.solid, width: 2)
                    ),
                  ),
                  _lShapeContainer(lPos: 0, side: 100),
                  _lShapeContainer(lPos: 10, side: 90),
                  _lShapeContainer(lPos: 20, side: 80),
                  _lShapeContainer(lPos: 30, side: 70),
                  _lShapeContainer(lPos: 40, side: 60),
                  _lShapeContainer(lPos: 50, side: 50),
                  _lShapeContainer(lPos: 60, side: 40),
                ],
              ),
            ],
          ),
        ),
      ),
    );}
    Widget _lShapeContainer({required double lPos, required double side}) {
     return Positioned(
      left: lPos,
      child: Container(
        width: side - 15,
        height: side,
        decoration: BoxDecoration(
            color: Colors.white60,
            border: Border.all(color: Colors.black, style: BorderStyle.solid, width: 2)
        ),
      ),
    );}}
    

    The output:

    l shaped image demo

    Updated: Responsive design

    Following is code where you can have a responsive shape. You need to adjust the height, width and multiplier according to your needs.

    class HomePage extends StatelessWidget {
     const HomePage({super.key});
    
     @override
     Widget build(BuildContext context) {
      final double height = 100;
      final double width = 100;
      final double multiplier = 10
      return Scaffold(
       appBar: AppBar(
        title: const Text('LShaped Design'),
        backgroundColor: Colors.blue,
       ),
       body: SizedBox(
        height: double.maxFinite,
        width: double.maxFinite,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              height: height,
              width: width + multiplier,
              color: Colors.red,
              child: AspectRatio(
                aspectRatio: 1/2,
                child: Stack(
                  children: <Widget>[
                    Container(
                      decoration: BoxDecoration(
                        color: Colors.white60,
                        border: Border.all(color: Colors.black, style: BorderStyle.solid, width: 2)
                      ),
                    ),
                    _lShapeContainer(lPos: 0, side: height, color: Colors.blue),
                    _lShapeContainer(lPos: (multiplier*1), side: height - (multiplier*1), color: Colors.white24),
                    _lShapeContainer(lPos: (multiplier*2), side: height - (multiplier*2), color: Colors.black26),
                    _lShapeContainer(lPos: (multiplier*3), side: height - (multiplier*3), color: Colors.green),
                    _lShapeContainer(lPos: (multiplier*4), side: height - (multiplier*4), color: Colors.amberAccent),
                    _lShapeContainer(lPos: (multiplier*5), side: height - (multiplier*5), color: Colors.redAccent),
                    _lShapeContainer(lPos: (multiplier*6), side: height - (multiplier*6), color: Colors.brown),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );}
      Widget _lShapeContainer({required double lPos, required double side, required Color color}) {
    return Positioned(
      left: lPos,
      child: Container(
        width: side - 15,
        height: side,
        decoration:
            BoxDecoration(color: color, border: Border.all(color: Colors.black, style: BorderStyle.solid, width: 2)),
      ),
    );}}
    
    1. Make the squares bigger:

    final double height = 200;
    final double width = 200;
    final double multiplier = 20;

    1. Change the right side vertical container width according to your need:

    width: width + multiplier,

    OR

    width: width,