I am trying to put some widgets in a row where the first widget should be square shaped and use the intrinsic width and height to modify the smaller one of these values so it results in a square shape. The side length should depend on the child widget, which is in my case a Text. Padding the text equally from all sides does not look right. I already tried achieving this with the AspectRatio
widget and its working as far as it results in the expected square shape, but it does not use the minimal space but rather scales up as much as possible.
Any idea how to get this result without hardcoding the width and height?
example code
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 100),
Text(' current status:'),
SizedBox(height: 5),
Row(
children: [
Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.red.shade300,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue),
),
child: const Center(
child: Text(
'square',
textAlign: TextAlign.center,
),
),
),
SizedBox(width: 10),
Flexible(
child: Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.blue.shade200,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.red),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'placeholder for other widgets',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
),
],
),
SizedBox(height: 50),
Text(' I want this:'),
SizedBox(height: 5),
Row(
children: [
SizedBox(
height: 50,
child: AspectRatio(
aspectRatio: 1,
child: Container(
decoration: BoxDecoration(
color: Colors.red.shade300,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue),
),
child: Center(
child: Text(
'square',
textAlign: TextAlign.center,
),
),
),
),
),
SizedBox(width: 10),
Flexible(
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.blue.shade200,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.red),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'placeholder for other widgets',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
),
],
),
],
),
),
);
}
}
EDIT:
my code looks like this now
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final GlobalKey _key = GlobalKey();
double boxWidth = 0.0;
final String inputText = 'square';
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
BuildContext? keyContext = _key.currentContext;
if (keyContext != null) {
RenderBox renderBox = keyContext.findRenderObject() as RenderBox;
boxWidth = renderBox.size.width;
}
});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 100),
Text(' input: $inputText'),
const SizedBox(height: 50),
const Text(' with StatefulWidget'),
const SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.all(10),
key: _key,
height: boxWidth,
decoration: BoxDecoration(
color: Colors.red.shade300,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue),
),
child: Center(
child: Text(
inputText,
textAlign: TextAlign.center,
),
),
),
const SizedBox(width: 10),
Flexible(
child: Container(
padding: const EdgeInsets.all(10),
height: boxWidth,
decoration: BoxDecoration(
color: Colors.blue.shade200,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.red),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'placeholder for other widgets',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
),
],
),
const SizedBox(height: 50),
const Text(' with AspectRatio'),
const SizedBox(height: 10),
Row(
children: [
Flexible(
flex: 2,
child: AspectRatio(
aspectRatio: 1,
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.red.shade300,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.blue),
),
child: Center(
child: Text(
inputText,
textAlign: TextAlign.center,
),
),
),
),
),
const SizedBox(width: 10),
Flexible(
flex: 8,
child: Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: Colors.blue.shade200,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.red),
),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'placeholder for other widgets',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
),
],
),
],
),
),
);
}
}
You can achieve this using flexible and aspect ratio
Row(
children : [
Flexible(
flex: 2,
child: AspectRatio(
aspectRatio: 1,
Container(
color: Colors.red,
)
)
),
Flexible(
flex: 8,
child: Text(),
)
]
)
You can change the flex value as per your requirement
Edit
You can use intrinsic height in a row to set the child to the tallest child
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
child: IntrinsicHeight(
child: Row(children: [
AspectRatio(aspectRatio: 1, child: Container(color: Colors.red)),
Flexible(
child: Text(
"djdjdjdhjvc gf\nf bg \nhg hshs\nfjgdhjfhj \n hxhkj \n fjdjd d \n ejejdj "))
])));
}
}