SingleChildScrollView rendering overflow when viewport greater than maxwidth - flutter

I'm trying to set web content to have a maximum width (the orange in the image), and always fill the available height, which I've achieved.
However when the window is wider than the maximum content width, and the window height is less than the height of the content, header, and footer combined. I'm getting a rendering overflow.
When what I'm after is for content to hold it's height, and the scroll to enable.
Note: the problem seems to go way if each text is only 1 line worth.
I've tried using CustomeScrollView with a SliverFillRemaining, but I get the same problem.
Any assistance would be greatly appreciated.
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 const MaterialApp(
title: 'Scrollable Layout',
home: ScrollableLayout(),
);
}
}
class ContentWidthContainer extends StatelessWidget {
final Widget child;
const ContentWidthContainer({Key? key, required this.child})
: super(key: key);
#override
Widget build(BuildContext context) {
return Container(
color: Colors.grey,
child: Align(
alignment: Alignment.topCenter,
child: Container(
color: Colors.orange,
width: double.infinity,
constraints: const BoxConstraints(
maxWidth: 960,
),
padding: const EdgeInsets.symmetric(horizontal: 75),
child: child),
),
);
}
}
class ScrollableLayout extends StatelessWidget {
const ScrollableLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Header: Fixed Height')),
),
Expanded(
child: ContentWidthContainer(
child: Container(
color: Colors.white,
child: Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
)),
),
),
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Footer: Fixed Height')),
),
],
),
),
),
);
},
),
);
}
}

If the height of the header and footer is 200 each, then the height of the middle content should be less than 400.
height: MediaQuery.of(context).size.height - 400
Therefore change your code to
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints)
{
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Header: Fixed Height')),
),
Expanded(
child: ContentWidthContainer(
child: Container(
height: MediaQuery.of(context).size.height - 400,
color: Colors.white,
child: Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
)),
),
),
ContentWidthContainer(
child: Container(
color: Colors.indigo,
height: 200,
child: const Text('Footer: Fixed Height')),
),
],
),
),
),
);
},
),
);
}

On changing it to use a Column, with just 2 children, and the alignment set to SpaceBetween, the overflow problem disappears when you make the window width but shorter than the content.
class ScrollableSpaceBetweenLayout extends StatelessWidget {
const ScrollableSpaceBetweenLayout({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return DefaultTextStyle(
style: Theme.of(context).textTheme.bodyText2!,
child: LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: Container(
color: Colors.black12, // the background / sides
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
color: Colors.indigo,
height: 200,
child: const Align(
alignment: Alignment.center,
child: Text('Header: Fixed Height'))),
Container(
color: Colors.orange,
constraints: BoxConstraints(
maxWidth: 960,
minHeight: max(viewportConstraints.maxHeight - 400, 0),
),
padding: const EdgeInsets.symmetric(horizontal: 75),
child: Container(
color: Colors.white,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
children: const [
Text(
'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
Text('Content'),
],
),
Container(
child: const Text('spacer'),
height: 1,
color: Colors.red)
],
)),
),
Container(
color: Colors.indigo,
height: 200,
child: const Align(
alignment: Alignment.center,
child: Text('Footer: Fixed Height'))),
],
),
),
);
},
),
);
}
}

Related

Flutter right overflow by 220 pixel

I have this error Flutter right overflow by 220 Pixel and Right Overflow error is showing.
My code :
import 'package:flutter/material.dart';
class Category extends StatelessWidget {
const Category({super.key});
Widget CategoryCard(String imgUrl, String CategoryName) {
return GestureDetector(
onTap: () {},
child: Container(
margin: EdgeInsets.only(right: 16),
child: Stack(
children: [
ClipRRect(borderRadius: BorderRadius.circular(6),child: Image.network(imgUrl,width: 120,height: 60,fit: BoxFit.cover,)),
Container(alignment: Alignment.center,width: 120,height: 60,decoration: BoxDecoration(borderRadius: BorderRadius.circular(6),color: Color.fromARGB(135, 0, 0, 0),),
child: Text(CategoryName,style: TextStyle(color: Colors.white, fontSize: 15),),
)],),),);
}
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Column(
children: [
Padding(padding: const EdgeInsets.all(10),child: Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: [CategoryCard("img1", "Technology"),CategoryCard("img2", "Technology"),CategoryCard("img3", "Technology"),CategoryCard("img4", "Technology")],
),),],),);}
}
Screenshot of ui and error:
Wrap your Row with SingleChildScrollView
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
// CategoryCard()
I modify your code and solved it ;)
first import below lines:
import 'dart:ui';
import 'package:flutter/material.dart';
then using Category and AppScrollBehavior class :
class Category extends StatelessWidget {
const Category({super.key});
Widget CategoryCard(String imgUrl, String CategoryName) {
return GestureDetector(
onTap: () {},
child: Container(
margin: EdgeInsets.only(right: 16),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: Image.network(
imgUrl,
width: 120,
height: 60,
fit: BoxFit.cover,
)),
Container(
alignment: Alignment.center,
width: 120,
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(6),
color: Color.fromARGB(135, 0, 0, 0),
),
// ignore: prefer_const_constructors
child: Text(
CategoryName,
style: TextStyle(color: Colors.white, fontSize: 15),
),
)
],
),
),
);
}
#override
Widget build(BuildContext context) {
return Column(
children: [
ScrollConfiguration(
behavior: AppScrollBehavior(),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Padding(
padding: const EdgeInsets.all(10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
CategoryCard("https://avatars.githubusercontent.com/u/46590079?v=4", "Technology"),
CategoryCard("https://avatars.githubusercontent.com/u/46590079?v=4", "Technology"),
CategoryCard("https://avatars.githubusercontent.com/u/46590079?v=4", "Technology"),
CategoryCard("https://avatars.githubusercontent.com/u/46590079?v=4", "Technology")
],
),
),
),
),
],
);
}
}
// if using flutter web need below class for enable scrolling
class AppScrollBehavior extends MaterialScrollBehavior {
#override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}

Make Listeview work nested inside of column inside of a container in flutter

I am trying and make a Listeview work, which is nested inside of column that is nested inside of a container in flutter. The container is supposed to be a dialog. I think the problem is that the container has no defined hight (it is supposed to adapt to the screen size). With the current code I get a bottom overflow. Maybe because of the padding of the container?
I tried differen variants with expanded, flexible and singlechildscrollview but I can't make it work. The standard tip, wrap the ListView with Expanded seems not to work.
Thanks for your help!
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: 'Dialog',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
MaCard(mitarbeiterName: "Name"),
CustomDialogBoxRow(
title: "Sturmtruppler",
descriptions: "wird noch weichen",
text: "text")
],
),
),
),
);
}
}
class Constants {
Constants._();
static const double padding = 20;
static const double avatarRadius = 100;
static const double buttonHight = 100;
}
class CustomDialogBoxRow extends StatefulWidget {
final String title, descriptions, text;
const CustomDialogBoxRow({
Key? key,
required this.title,
required this.descriptions,
required this.text,
}) : super(key: key);
#override
_CustomDialogBoxRowState createState() => _CustomDialogBoxRowState();
}
class _CustomDialogBoxRowState extends State<CustomDialogBoxRow> {
#override
Widget build(BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(Constants.padding),
),
elevation: 0,
backgroundColor: Colors.transparent,
child: contentBox(context),
);
}
contentBox(context) {
return Stack(
children: <Widget>[
Container(
constraints: const BoxConstraints(minWidth: 400, maxWidth: 800),
padding: const EdgeInsets.only(
left: Constants.padding,
right: Constants.padding,
bottom: Constants.padding),
margin: const EdgeInsets.only(top: Constants.avatarRadius),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(Constants.padding),
boxShadow: [
const BoxShadow(
color: const Color.fromARGB(255, 79, 73, 73),
offset: const Offset(0, 5),
blurRadius: 5),
]),
child: Column(
children: [
SizedBox(
height: Constants.avatarRadius,
child: Row(
children: [
const SizedBox(
child: const Placeholder(),
),
const Expanded(
child: Placeholder(),
),
],
),
),
SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
)
],
),
)
],
),
),
Positioned(
left: Constants.padding,
right: Constants.padding,
child: Stack(
children: [
Container(
child: Align(
alignment: Alignment.topLeft,
child: Container(
width: Constants.avatarRadius * 2,
height: Constants.avatarRadius * 2,
child: const CircleAvatar(
radius: Constants.avatarRadius * 2,
backgroundImage: AssetImage('assets/images/SBE.jpg'),
),
),
),
),
],
),
),
],
);
}
}
class MaCard extends StatefulWidget {
MaCard({
Key? key,
required this.mitarbeiterName,
}) : super(key: key);
final String mitarbeiterName;
#override
State<MaCard> createState() => _MaCardState();
}
class _MaCardState extends State<MaCard> {
#override
Widget build(BuildContext context) {
return Card(
child: InkWell(
onTap: () {
print("card taped");
/*showDialog(context: context, builder: (BuildContext context) {
return
})*/
showDialog(
context: context,
builder: (BuildContext context) {
return CustomDialogBoxRow(
title: "Stormtrouper",
descriptions: "Jojo, this is card",
text: "Roger Roger",
);
});
},
child: SizedBox(
height: Constants.buttonHight,
width: 300,
child: Center(child: Text(widget.mitarbeiterName)),
),
));
}
}
Here is picture of what it should look like. My wonderful handdrawing is supposed to be the scrollable content.
Goal
It would be better using LayoutBuilder to get parent constraints and size the inner elements. Also You need to wrap with Expaned to get available spaces for infinite size widget.
I will highly recommend to check this video from Flutter.
Changes are made
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Dialog',
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Center(
child: Column(
children: [
MaCard(mitarbeiterName: "Name"),
Expanded( //here
child: CustomDialogBoxRow(
title: "Sturmtruppler",
descriptions: "wird noch weichen",
text: "text"),
)
],
),
),
),
);
}
}
And on contentBox
contentBox(context) {
return LayoutBuilder(builder: (context, constraints) {
print(constraints);
return SizedBox(
width: constraints.maxWidth,
height: constraints.maxHeight,
child: Stack(
children: <Widget>[
Container(
constraints: const BoxConstraints(minWidth: 400, maxWidth: 800),
padding: const EdgeInsets.only(
left: Constants.padding,
right: Constants.padding,
bottom: Constants.padding),
margin: const EdgeInsets.only(top: Constants.avatarRadius),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
color: Colors.white,
borderRadius: BorderRadius.circular(Constants.padding),
boxShadow: const [
BoxShadow(
color: Color.fromARGB(255, 79, 73, 73),
offset: Offset(0, 5),
blurRadius: 5),
]),
child: Column(
children: [
SizedBox(
height: Constants.avatarRadius,
child: Row(
children: [
const Expanded(
child: const Placeholder(),
),
const Expanded(
child: Placeholder(),
),
],
),
),
Expanded(
// or sizedBOx ( constraints.maxHeight- Constants.avatarRadius,)
child: SingleChildScrollView(
child: Column(
children: [
SizedBox(
height: 450,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
),
SizedBox(
height: 50,
child: Text("bla"),
)
],
),
),
)
],
),
),
// Positioned(
// left: Constants.padding,
// right: Constants.padding,
// child: Stack(
// children: [
// Container(
// child: Align(
// alignment: Alignment.topLeft,
// child: Container(
// width: Constants.avatarRadius * 2,
// height: Constants.avatarRadius * 2,
// child: const CircleAvatar(
// radius: Constants.avatarRadius * 2,
// backgroundImage: AssetImage('assets/images/SBE.jpg'),
// ),
// ),
// ),
// ),
// ],
// ),
// ),
//
],
),
);
});
}

Flutter set widget position exactly center of the screen

I want to put a container widget in the middle of the device screen. However, since I used the SizedBox() and SvgPicture.asset() widgets before that, the container does not come right in the middle of the device. How can I do this?
This is my code:
class CenterWidget extends StatefulWidget {
const CenterWidget({Key? key}) : super(key: key);
#override
_CenterWidgetState createState() => _CenterWidgetState();
}
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
Expanded(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}
Use a top center aligned stack, and put the widget you want to be centered within a Positioned.fill widget. You can put the spacer and logo in their own column to keep them arranged vertically:
class _CenterWidgetState extends State<CenterWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: Stack(
alignment: Alignment.topCenter,
children: [
Column(
children: [
const SizedBox(height: 56),
SvgPicture.asset(ImageConstants.instance.logoSvg,
width: (MediaQuery.of(context).size.width - 60) / 2),
],
),
Positioned.fill(
child: Center(
child: Container(
color: Colors.red,
width: 100,
height: 100,
),
),
),
],
),
),
),
);
}
}

is there a way to embed a SingleChildScrollView (Vertical) within another SingleChildScrollView(Horizontal) in Flutter

In my app there is a SingleChildScrollView(with scrollable direction as Horizontal) which has a N number of containers.
Is there a way to embed a the SingleChildScrollView(with scrollable direction as Horizontal) into a SingleChildScrollView (with scrollable direction as Vertical) in Flutter.
for example:
class HomeBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SafeArea(
child: Padding(
padding: sidePadding,
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
HomeAppbar(),
addVerticalSpace(15),
Text(
'Welcome, Jack',
style: themeData.textTheme.headline1,
),
addVerticalSpace(15),
SearchField(
width: mediasize.width - 2 * screenHorizontalPadding,
height: mediasize.height,
),
addVerticalSpace(25),
//I want to add a SingleChildScrollView (Vertical Direction) from this point to
TitleMoreBar(barTitle: 'Trending'),
addVerticalSpace(15),
//the FullProductCardHorizontalList() has a SingleChildScrollView(Horizontal direction)
FullProductCardHorizontalList(),
addVerticalSpace(25),
TitleMoreBar(barTitle: 'Popular Brands'),
addVerticalSpace(25),
//the BrandCardList() has a SingleChildScrollView(Horizontal direction)
BrandCardList(),
// this where the SingleChildScrollView (Vertical) should end
],
),
),
),
);
}
Yes, you can do this like:
import 'package:flutter/material.dart';
class ScrollTraining extends StatefulWidget {
#override
_ScrollingTraining createState() => _ScrollingTraining();
}
class _ScrollingTraining extends State<ScrollTraining> {
double mWidth;
#override
Widget build(BuildContext context) {
mWidth = MediaQuery.of(context).size.width;
return Scaffold(
appBar: AppBar(),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: mWidth,
height: 400,
color: Colors.indigo,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
Container(
width: mWidth,
height: 400,
color: Colors.brown,
margin: EdgeInsets.symmetric(vertical: 8.0),
alignment: Alignment.center,
child: Text("Fixed Box"),
),
Container(
width: mWidth,
height: 200,
margin: EdgeInsets.symmetric(vertical: 8.0),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: getChildren(),
),
),
),
],
),
),
);
}
List<Widget> getChildren() {
List<Widget> output = List();
List<Color> colorList = [
Colors.redAccent,
Colors.deepOrange,
Colors.orangeAccent,
Colors.yellow,
Colors.lightGreenAccent,
Colors.green,
Colors.greenAccent,
Colors.blue,
Colors.purpleAccent,
Colors.pink,
];
for (int i = 0; i < 10; i++) {
output.add(Container(
width: 140,
height: 200,
color: colorList[i],
));
}
return output;
}
}
I hope it is useful for you.

How to prevent Row from taking all available width?

I have one problem with my CustomChip :
I need to wrap the card to fit the content only.
However, I have a second requirement: The long text should overflow fade.
When I fixed the second problem, this issue started to occur when I added Expanded to wrap the inner Row
I don't understand why the inner Row also seems to expand although its mainAxisSize is already set to min
Here is the code:
The screen:
import 'package:flutter/material.dart';
import 'package:app/common/custom_chip.dart';
class RowInsideExpanded extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
),
),
width: 200.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildChip('short'),
_buildChip('looooooooooooooooooooooongg'),
],
),
),
),
);
}
_buildChip(String s) {
return Row(
children: [
Container(
color: Colors.red,
width: 15,
height: 15,
),
Expanded(
child: CustomChip(
elevation: 0.0,
trailing: Container(
decoration: BoxDecoration(
color: Colors.grey,
shape: BoxShape.circle,
),
child: Icon(Icons.close),
),
onTap: () {},
height: 42.0,
backgroundColor: Colors.black12,
title: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
s,
softWrap: false,
overflow: TextOverflow.fade,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 16.0),
),
),
),
),
],
);
}
}
And the CustomChip
import 'package:flutter/material.dart';
class CustomChip extends StatelessWidget {
final Widget leading;
final Widget trailing;
final Widget title;
final double height;
final double elevation;
final Color backgroundColor;
final VoidCallback onTap;
const CustomChip({
Key key,
this.leading,
this.trailing,
this.title,
this.backgroundColor,
this.height: 30.0,
this.elevation = 2.0,
this.onTap,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
elevation: elevation,
color: backgroundColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
child: InkWell(
onTap: onTap,
child: Container(
height: height,
child: Padding(
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
leading ?? Container(),
SizedBox(
width: 5.0,
),
Flexible(
child: title,
fit: FlexFit.loose,
),
SizedBox(
width: 5.0,
),
trailing ?? Container(),
],
),
),
),
),
);
}
}
Look for "MainAxisSize" property and set to "MainAxisSize.min"
Instead of Expanded, just replace it with a Flexible that's because Expanded inherits Flexible but set the fit proprety to FlexFit.tight
When fit is FlexFit.tight, the box contraints for any Flex widget descendant of a Flexible will get the same box contraints. That's why your Row still expands even though you already set its MainAxisSize to min.
I changed your code to print the box contraints using a the LayoutBuilder widget.
Consider your code with Expanded:
import 'package:flutter/material.dart';
class RowInsideExpanded extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
),
),
width: 200.0,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
_buildChip('short'),
SizedBox(
height: 5,
),
_buildChip('looooooooooooooooooooooongg'),
],
),
),
),
);
}
_buildChip(String s) {
return Row(
children: [
Container(
color: Colors.red,
width: 15,
height: 15,
),
Expanded(
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
print("outter $constraints");
return Container(
color: Colors.greenAccent,
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
print("inner $constraints");
return Row(
mainAxisSize: MainAxisSize.min, // this is ignored
children: <Widget>[
SizedBox(
width: 5.0,
),
Flexible(
fit: FlexFit.loose,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Text(
s,
softWrap: false,
overflow: TextOverflow.fade,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.bold, fontSize: 16.0),
),
),
),
SizedBox(
width: 5.0,
),
Container(
decoration: BoxDecoration(
color: Colors.grey,
shape: BoxShape.circle,
),
child: Icon(Icons.close),
),
],
);
}),
);
}),
),
],
);
}
}
It prints
I/flutter ( 7075): outter BoxConstraints(w=183.0, 0.0<=h<=Infinity)
I/flutter ( 7075): inner BoxConstraints(w=183.0, 0.0<=h<=Infinity)
(Look at the width in w, it constrained to be 183.0 for both outter and inner Row)
Now I changed the Expanded to Flexible and check the logs:
I/flutter ( 7075): outter BoxConstraints(0.0<=w<=183.0, 0.0<=h<=Infinity)
I/flutter ( 7075): inner BoxConstraints(0.0<=w<=183.0, 0.0<=h<=Infinity)
(Look at the width in w, it constrained to between zero and 183.0 for both outter and inner Row)
Now your widget is fixed: