3

I have a CustomPaint that needs to be a 1:1 square, and I need to put this in a Row. The horizontal and vertical space available can vary, so I need both the length and width of the square to be the smallest maximum constraint.

How can I achieve this behaviour?

I've tried using LayoutBuilder for this:

Row(
  children: [
    ...,
    LayoutBuilder(
      builder: (context, constraints) {
        final size = min(constraints.maxWidth, constraints.maxHeight);
        return SizedBox(
          width: size,
          height: Size,
          child: CustomPaint(...),
        ),
      },
    ),
  ]
),

This, however, doesn't work, because Row provides unbounded horizontal constraints (maxWidth == double.infinity). Using the FittedBox widget also fails for the same reason.

Wrapping the LayoutBuilder in an Expanded widget provides it with a bounded maximum width, but I need to have another widget next to it in the Row, so this is not appropriate. Flexible behaves like Expanded in this case, as well.

hacker1024
  • 3,186
  • 1
  • 11
  • 31

3 Answers3

4

I think you can get what you want from the AspectRatio widget... if you tell it 1:1, then it tries to make a square unless completely not possible.

Randal Schwartz
  • 39,428
  • 4
  • 43
  • 70
  • Unfortunately, `AspectRatio` uses the height to calculate the width. This is not appropriate in this situation, as it doesn't take any width constraints into account. – hacker1024 Dec 24 '20 at 06:42
  • This may not have answered the question as written, but it did solve the issue I had when I found this question. Thank you! – Jonathan Nov 17 '21 at 20:12
0

Please try the code below, using Align widget restrains the widget to a square :

import 'package:flutter/material.dart';
import 'dart:math';

final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: MyWidget(),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          flex: 1,
          child: Container(),
        ),
        Expanded(
          flex: 2,
          child: LayoutBuilder(
            builder: (context, constraints) {
              final size = min(constraints.maxWidth, constraints.maxHeight);
              return Align(
                alignment: Alignment.centerRight,
                child: Container(
                  height: size,
                  width: size,
                  color: Colors.amber,
                ),
              );
            },
          ),
        ),
        // Expanded(
        //   flex: 1,
        //   child: Container(),
        // ),
      ],
    );
  }
}
bluenile
  • 5,673
  • 3
  • 16
  • 29
0

I ended up working this issue by moving the responsibility of keeping the widget square up the tree. Widgets that were using the square widget knew more about what other things they were showing and were more capable of giving it the right constraints.

hacker1024
  • 3,186
  • 1
  • 11
  • 31
  • Answers are still welcome, as I haven't really worked out the answer to my question yet, I've just worked around it. – hacker1024 Dec 24 '20 at 10:55