skip to Main Content

I want align the following nested list in such a way that black line should be horizontally center of the green box (parent list) i cant add any padding or extra space or positioned or increase the red column width

please note black line is for reference the line actually not part of the code

enter image description here

dartpad ready code here

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Horizontal List of Vertical Lists')),
        body: ParentLayout(),
      ),
    );
  }
}

class ParentLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        // Header content (Green Box at the top)
        Container(
          height: 100,
          width: 200,
        
          color: Colors.green[100],
          child: Center(child: Text("Parent ListView Content Above")),
        ),

        // Horizontal layout with dividing line centered to green boxes
        Expanded(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // Blue List
              _generateBlueList(),

              // Dividing line
     
              // Red List
              _generateRedList(),
            ],
          ),
        ),

        // Footer content (Green Box at the bottom)
        Container(
          height: 100,
          width: 200,
          color: Colors.green[100],
          child: Center(child: Text("Parent ListView Content Below")),
        ),
      ],
    );
  }

  // Generate blue list with varying sizes
  Widget _generateBlueList() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(
        5,
        (innerIndex) => Container(
          height: 40 + (innerIndex * 25), // Varying height
          width: 80 + (innerIndex * 40), // Varying width
          color: Colors.blue[100 * (innerIndex + 1)],
          child: Center(
            child: Text(
              'Blue $innerIndex',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }

  // Generate red list with fixed sizes
  Widget _generateRedList() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: List.generate(
        5,
        (innerIndex) => Container(
          height: 60, // Fixed height
          width: 100, // Fixed width
          color: Colors.red[100 * (innerIndex + 1)],
          child: Center(
            child: Text(
              'Red $innerIndex',
              style: TextStyle(color: Colors.white),
            ),
          ),
        ),
      ),
    );
  }
}

2

Answers


  1. Chosen as BEST ANSWER

    I did bit of math to find necessary x axis translate, and achieved it.

    to make the other neighbouring widget respect the translated widget position, im adding padding to entire parent column. And its not wasting the space, because transformed widget is laying there.

    enter image description here

    [![import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: Text('Dynamic Horizontal List')),
            body: ParentLayout(),
          ),
        );
      }
    }
    
    class ParentLayout extends StatefulWidget {
      @override
      _ParentLayoutState createState() => _ParentLayoutState();
    }
    
    class _ParentLayoutState extends State<ParentLayout> {
      final GlobalKey _blueKey = GlobalKey();
      final GlobalKey _redKey = GlobalKey();
    
      double _blueListWidth = 0;
      double _redListWidth = 0;
    
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) => _updateWidths());
      }
    
      void _updateWidths() {
        final blueRenderBox = _blueKey.currentContext?.findRenderObject() as RenderBox?;
        final redRenderBox = _redKey.currentContext?.findRenderObject() as RenderBox?;
    
        if (blueRenderBox != null && redRenderBox != null) {
          final double newBlueListWidth = blueRenderBox.size.width;
          final double newRedListWidth = redRenderBox.size.width;
    
          // Update state only if widths have changed
          if (_blueListWidth != newBlueListWidth || _redListWidth != newRedListWidth) {
            setState(() {
              _blueListWidth = newBlueListWidth;
              _redListWidth = newRedListWidth;
            });
          }
        }
      }
    
      @override
      Widget build(BuildContext context) {
        // Calculate the translation for the entire row based on which list is wider
        final double rowTranslation = (_blueListWidth > _redListWidth)
            ? -((_blueListWidth - _redListWidth) / 2) // Translate left if blue is wider
            : ((_redListWidth - _blueListWidth) / 2); // Translate right if red is wider
    
        // Calculate dynamic padding for the parent list view
        final EdgeInsets parentPadding = EdgeInsets.only(
          left: rowTranslation < 0 ? rowTranslation.abs() : 0, // Padding on left
          right: rowTranslation > 0 ? rowTranslation.abs() : 0, // Padding on right
        );
    
        return Padding(
          padding: parentPadding, // Apply dynamic padding
          child: Column(
            children: [
              // Header content (Green Box at the top)
              Container(
                height: 100,
                width: 200,
                color: Colors.green[100],
                child: Center(child: Text("Parent ListView Content Above")),
              ),
    
              // Horizontal layout with dividing line centered to green boxes
              IntrinsicHeight(
                child: Transform.translate(
                  offset: Offset(rowTranslation, 0), // Translate based on the width difference
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    mainAxisSize: MainAxisSize.min,
                    crossAxisAlignment: CrossAxisAlignment.start, // Align to the top of the Row
                    children: [
                      // Blue List wrapped in IntrinsicWidth
                      IntrinsicWidth(
                        child: Container(
                          key: _blueKey,
                          color: Colors.blue.withOpacity(0.2), // Background for visual distinction
                          child: _generateBlueList(),
                        ),
                      ),
    
                      // Divider
                      Container(
                        width: 2,
                        color: Colors.grey,
                        margin: EdgeInsets.symmetric(horizontal: 8),
                      ),
    
                      // Red List wrapped in IntrinsicWidth
                      IntrinsicWidth(
                        child: Container(
                          key: _redKey,
                          color: Colors.red.withOpacity(0.2), // Background for visual distinction
                          child: _generateRedList(),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
    
              // Footer content (Green Box at the bottom)
              Container(
                height: 100,
                width: 200,
                color: Colors.green[100],
                child: Center(child: Text("Parent ListView Content Below")),
              ),
            ],
          ),
        );
      }
    
      // Generate blue list with varying sizes
      Widget _generateBlueList() {
        return Column(
          mainAxisAlignment: MainAxisAlignment.start, // Align items to the top
          children: List.generate(
            5,
            (innerIndex) => Container(
              height: 40 + (innerIndex * 25), // Varying height
              width: 80 + (innerIndex * 40), // Varying width
              color: Colors.blue[100 * (innerIndex + 1)],
              child: Center(
                child: Text(
                  'Blue $innerIndex',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        );
      }
    
      // Generate red list with fixed sizes
      Widget _generateRedList() {
        return Column(
          mainAxisAlignment: MainAxisAlignment.start, // Align items to the top
          children: List.generate(
            5,
            (innerIndex) => Container(
              height: 60, // Fixed height
              width: 100, // Fixed width
              color: Colors.red[100 * (innerIndex + 1)],
              child: Center(
                child: Text(
                  'Red $innerIndex',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        );
      }
    }
    

  2. Here’s what you want,

    enter image description here

    just changing some cross axis alignments of both columns of green and red containers, and i have added expanded widget.

    Here’s your refactored code:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          home: Scaffold(
            appBar: AppBar(title: Text('Horizontal List of Vertical Lists')),
            body: ParentLayout(),
          ),
        );
      }
    }
    
    class ParentLayout extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            // Header content (Green Box at the top)
            Container(
              width: 200,
              color: Colors.green[100],
              child: Center(child: Text("Parent ListView Content Above")),
            ),
    
            // Horizontal layout with dividing line centered to green boxes
            Expanded(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Blue List
                  Expanded(child: _generateBlueList()),
    
                  
    
                  // Red List
                  Expanded(child: _generateRedList()),
                ],
              ),
            ),
    
            // Footer content (Green Box at the bottom)
            Container(
              width: 200,
              color: Colors.green[100],
              child: Center(child: Text("Parent ListView Content Below")),
            ),
          ],
        );
      }
    
      // Generate blue list with varying sizes
      Widget _generateBlueList() {
        return Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: List.generate(
            5,
            (innerIndex) => Container(
              height: 40 + (innerIndex * 25), // Varying height
              width: 80 + (innerIndex * 40), // Varying width
              color: Colors.blue[100 * (innerIndex + 1)],
              child: Center(
                child: Text(
                  'Blue $innerIndex',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        );
      }
    
      // Generate red list with fixed sizes
      Widget _generateRedList() {
        return Column(
          crossAxisAlignment : CrossAxisAlignment.start, 
          mainAxisAlignment: MainAxisAlignment.start,
          children: List.generate(
            5,
            (innerIndex) => Container(
              height: 60, // Fixed height
              width: 100, // Fixed width
              color: Colors.red[100 * (innerIndex + 1)],
              child: Center(
                child: Text(
                  'Red $innerIndex',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search