How do I tweak my Flutter Stack widget to not have bottom overflowing? - flutter

[Update] : I got the solution, If you want the code, comment below or if you just want to know I've written it here :
The solution is to put the Cover Image and the Followers & Following inside a Column (as a single widget) and then put that Column and the Align (profile picture) both inside a Stack, then set the Fixed heightFactor.
So it would look something like this :
Stack(
children: <Widget>[
Column(
children: <Widget>[
Container(), //The Cover Photo
Container(
child: Card() //The Followers and Following Card
)
]
),
Align() //The Profile Picture having fixed heightFactor
]
)
This solution is working on all 4 Devices I have + 2 Android Emulators (2 have 16:9 ratio, 2 have 18:9 and 2 have 19:9 ratio).
The problem is following :
On my device, which is having 18:9 Aspect Ratio there is no Bottom Overflowing issue.
But on devices having 16:9 Aspect Ratio it's having this issue.
This happens only when I try to set heightFactor of Followers & Following Align widget.
I tried to tweak many things in Stack so I could overcome this, but couldn't achieve similar result. So, I'm stuck with this.
Also, as far as I know I can overlap only by using Stack widget. If there is any possible option, do say.
Here is my code :
Stack(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width,
height: 224.0,
margin: EdgeInsets.all(8.0),
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(8.0),
image: DecorationImage(
image: NetworkImage("https://www.eta.co.uk/wp-content/uploads/2012/09/Cycling-by-water-resized-min.jpg"),
fit: BoxFit.cover
)
),
),
Align(
heightFactor: 5.0,
child: Container(
alignment: Alignment.bottomCenter,
width: MediaQuery.of(context).size.width,
height: 96.0,
margin: EdgeInsets.all(8.0),
child: Card(
color: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
elevation: 0.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
"Followers",
style: TextStyle(
fontFamily: "Nunito",
fontWeight: FontWeight.bold,
color: Colors.blue
),
),
Text(
"3000",
style: TextStyle(
fontFamily: "Nunito",
color: Colors.blue
),
),
],
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
"Following",
style: TextStyle(
fontFamily: "Nunito",
fontWeight: FontWeight.bold,
color: Colors.blue
),
),
Text(
"0",
style: TextStyle(
fontFamily: "Nunito",
color: Colors.blue
),
),
],
),
],
),
),
),
),
Align(
alignment: Alignment.bottomCenter,
heightFactor: 2.75,
child: Card(
color: Colors.transparent,
elevation: 0.0,
child: Container(
alignment: Alignment.bottomCenter,
width: 96.0,
height: 96.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: NetworkImage("https://cdn140.picsart.com/284302087007201.jpg?c256x256"),
fit: BoxFit.fill
),
border: Border.all(width: 4.0, color: Colors.blue)
),
),
),
),
],
),

You've provided the height of widget manually so it'll overflow on smaller screens. So you have to provide the height of widget depending upon the screen. You can use MediaQuery.of(context).size.height to get the height of the device.
And you can also multiply it with some number to get the height in percentage. For example, if you want 80% height of the screen then you can do MediaQuery.of(context).size.height * 80

The answer from #yashthakkar1173 is correct. That's one way of doing it. In addition to that I would say to his solution you can use
ConstrainedBox(
child: Card(),
constraints: BoxConstraints(
minHeight: 96.0,
maxHeight: 106.0,
))
What I observe is that you don't need the entire view to be in a Stack since it's just the top three widgets that overlap so I would wrap that stack in a column and set MainAxisSize to Min. I've done something similar, or you can set it to max so it'll always fill all the space left over.

Related

Getting a Container inside an Expanded inside a Row to expand vertically to fit the space available in the Row

I have a row containing four Expanded widgets. Its code looks as follows:
Row(
children: [
Expanded(
child: Container(
width: double.infinity,
color: Colors.blueGrey,
padding: const EdgeInsets.all(10),
child: (Text(
lessonData.language,
style: const TextStyle(
color: Colors.white,
),
)),
),
),
Expanded(
flex: 1,
child: Container(
width: double.infinity,
color: Colors.blueGrey,
padding: const EdgeInsets.all(10),
child: (Text(
lessonData.cEFRLevelName,
style: const TextStyle(
color: Colors.white,
),
)),
),
),
Expanded(
flex: 1,
child: Container(
width: double.infinity,
color: Colors.blueGrey,
padding: const EdgeInsets.all(10),
child: (Text(
lessonData.lessonTopic,
style: const TextStyle(
color: Colors.white,
),
)),
),
),
Expanded(
child: Container(
width: double.infinity,
color: Colors.blueGrey,
padding: const EdgeInsets.all(10),
child: (
Text(
lessonData.lessonHeading,
style: const TextStyle(
color: Colors.white,
),
)),
),
)
],
),
The resulting display is unsatisfactory if any of the texts in the Containers inside the Expanded widgets are forced to wrap. As in this image:
Click here to display an image of my problem when text has wrapped in one Container but not in the other three.
This image shows something like what I'd like the Row to look like.
I simply can't get the Container widgets containing text without any wrap to expand out to the height of the row.
Among other candidate solutions, I've tried setting the height to double.infinity and double.maxFinite, setting Constraints in the Containers to Constraints: BoxConstraints.expand(). All these options either do nothing or generate an error on hot reload.
I'm reluctant to try an IntrinsicHeight widget because I'm warned that it's very hungry.
I'd be very grateful for any solution and/or comment you might have!
TIA
Jaime
If I understood what you want, I may have a suggestion. It's more of a workaround, but you can move the Container with the colored backgroud up a level and remove each other Container, making the new Container the parent of the whole Row: I put the code in a DartPad, and this is how it looks.
Just an excerpt of the code:
Container(color: Colors.red,child: Row(
children: [
Expanded(...),
Expanded(...),
//and so on...
This works only on an aesthetic level: each Text will still get resized, but you won't notice.

Need Text to stay within the width of the image and wrap around

I have a column inside a listview. The column has image at the top and text in the bottom. I would like the text to stay within the width of the image and wrap. Right now the text does not wrap. Here is how the image and text in the column look like. Any body know how to do that?
Thanks in advance.
Here is the code of the column:
Row(
children: [
Container(
alignment: Alignment.centerRight,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: BorderRadius.circular(12),
border: Border.all(width: 1, color: AppColors.pink2),
),
child: Column(
children: [
ConstrainedBox(
constraints:
BoxConstraints(maxHeight: 300, maxWidth: width - 50),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image(
image: MemoryImage(chatMessageModel.rawData!),
fit: BoxFit.cover,
),
),
),
Padding(
padding: const EdgeInsets.all(14),
child: Text('I need this text to wrap around'),
),
],
),
),
],
)
You can use Flexible with AutoSizeText Widget to make it possible.
AutoSizeText Widget align your text size by corresponding your screen size
Flexible Widget adjust your text position
Working code :
Flexible(
child: AutoSizeText(
'I need this text to wrap around',
style: const TextStyle(
fontWeight: FontWeight.w400,
color: Color.fromRGBO(0, 0, 0,
1), //rankingNoColors(index)
fontSize: 24.0,
fontStyle: FontStyle.normal,
),
),
);

How to stack two icons one on top of the other?

I have two icons in a stack. I want one to hide the other, but instead it's semi-transparent and the other is shown behind it.
This is the code:
Stack(
children: [
Container(child: Icon(Icons.account_circle_rounded), padding: EdgeInsets.only(left: 10),),
Container(child: Icon(Icons.account_circle_rounded), padding: EdgeInsets.only(left: 20),),
],
)
This is how it looks:
Icons are more like SVG, use vector to draw shape. There are some empty spaces inside the icon to draw the path, and we can see the background though this. Also, it contains padding around it, You can use your assets to draw the UI.
We can wrap with another ColoredBox to hide the background icon, but it will get extra padding from IconData.
This snippet shows basic level structure.
SizedBox(
height: 24,
width: 24 * 1.7,
child: Stack(
alignment: Alignment.center,
children: [
Align(
alignment: Alignment.centerLeft,
child: Container(
child: const Icon(
Icons.account_circle_rounded,
),
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
),
Align(
alignment: Alignment.centerRight,
child: Container(
child: const Icon(
Icons.account_circle_sharp,
),
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
),
),
],
),
),
Widget renders bottom to top.

How to wrap and scale down text at the same time in flutter?

I have a text inside circular container and that text is coming from an API. So I have no control over the length of the text. I show that text inside container despite of how long it is by scaling it down with FittedBox.
Container(
height: 44,
width: 44,
padding: EdgeInsets.all(3),
alignment: Alignment.center,
child: Row(
children: [
Flexible(
child: FittedBox(
child: Text('Best Seller'),
),
),
],
),
decoration: BoxDecoration(shape: BoxShape.circle, color: Color(0xFFF37C43)),
)
My question is how can I show all the words of the text in new line while scaling them down as well. I was thinking about using Column and generating child widgets from each word of the text. But it does not seem very intuitive. I am open to change my layout design if that is what is required.
Container(
height: 44,
width: 44,
padding: EdgeInsets.all(3),
alignment: Alignment.center,
child: Wrap(
children: [
Text('Best Seller', style: TextStyle(fontSize: 10),),
],
),
decoration:
BoxDecoration(shape: BoxShape.circle, color: Color(0xFFF37C43)),
),
try setting the fontSize compatible with the length of the word. example:
Text(
myString,
style: TextStyle(
fontSize: myString.length > 60? 30: myString.length > 40? 40 : 50,
),
)

Make container grow to fit width of sibling in column

I have two Container widgets in a Column, each containing a Text widget. I want the Container with the shortest text to expand to match the width of the other container containing the longer text. The container with the longer text should wrap the Text widget and its padding.
I can't get it to work without resorting to fixed widths on the containers:
return Column(
mainAxisSize: MainAxisSize.min,
children: [
// This container has a shorter text than its sibling, so it should expand
// its width to match its sibling/parent
Container(
alignment: Alignment.center,
width: 50, // I don't want this fixed width
decoration: BoxDecoration(color: Colors.orange, borderRadius: BorderRadius.only(topLeft: Radius.circular(4), topRight: Radius.circular(4))),
child: Padding(
padding: const EdgeInsets.fromLTRB(8,4,8,4),
child: Text('short'),
)
),
// This container has a longer text, so it should decide the width of the
// other container (and of the parent Column)
Container(
alignment: Alignment.center,
width: 50, // I don't want this fixed width
decoration: BoxDecoration(color: Colors.orange, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(4), bottomRight: Radius.circular(4))),
child: Padding(
padding: const EdgeInsets.fromLTRB(8,4,8,4),
child: Text('long text here'),
)
),
]
);
I've tried a couple of ways to solve it involving Expanded and Flexible, but they all result in the "red screen of death" (or at least "annoyance").
EDIT
Just to be clear - I want the Column to just wrap its content, i.e. adjust its width to the width of the containers. In summary - everything should be as narrow as possible, except for the container with the shortest text, which should instead be as wide as its sibling (the container with the longer text).
I saw your Fiddle on a comment. And what you need is IntrinsicWidth.
IntrinsicWidth(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// This container has a shorter text than its sibling, so it should expand
// its width to match its sibling/parent
Padding(
padding: const EdgeInsets.symmetric(vertical: 1.0),
child: Container(
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 4, 8, 4),
child: Text(
'short',
textAlign: TextAlign.center,
),
),
),
),
// This container has a longer text, so it should decide the width of the
// other container (and of the parent Column)
Padding(
padding: const EdgeInsets.symmetric(vertical: 1.0),
child: Container(
color: Colors.orange,
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 4, 8, 4),
child: Text(
'long text here',
textAlign: TextAlign.center,
),
),
),
),
],
),
),
You can use something like this to take the entire width of the Widget (make sure to be inside a MaterialApp and a Scaffold/Material child (home):
Wrap(
children: <Widget>[
Container(
color: Colors.red,
child: IntrinsicWidth(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
color: Colors.black,
height: 200,
child: Align(
alignment: Alignment.bottomRight,
child: Text(
"Hello World",
style: TextStyle(color: Colors.white),
),
),
),
Container(
color: Colors.blue,
height: 100,
child: Align(
alignment: Alignment.topRight,
child: Text(
"Bottom Text Longer Text",
style: TextStyle(color: Colors.white),
),
),
),
],
),
),
),
],
)
The Align is not necessary, is just to showcase how the width actually works with "double.infinity" and moving a text to the bottom right or top right portion of it.