While waiting for an upcoming event, I slowly roll a Text() showing an emoji.
I use the code below:
Container(
padding: EdgeInsets.all(contentPadding),
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.all(Radius.circular(40))),
child: widget.status == null
? Column(children: [
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Transform(
transform: Matrix4.rotationZ(rot.value),
alignment: Alignment.center,
child: Text(
text,
style: style,
)),
CircularProgressIndicatorWithOptions(),
]),
Text(sumUp),
])
: Column(children: [
Text(text, style: style),
Text(""),
Text(sumUp),
])));
Here is the issue that appears only on some android phones:
And on others phones, it is ok:
How to make sure the text keeps is intrinsic natural size? (aka, not using a SizedBox with a specific size).
I've got a workaround by adding a small scale as follows:
Transform.scale(
scale: 0.96,
child: Transform.rotate(
angle: _turnsAnim.value,
child: Text(text, style: style))),
I believe that on some phones, the widget comes out of bounding box which triggers the scale up effect.
I put more time soon to try to demonstrate this hypothesis.
Related
I'm building a message tile for chat screen in the flutter. I'm making the use of spaceBetween property of mainAxisAlignment in row to keep both text widget apart from each other but it's not making any impact
here is my code
Row(
mainAxisAlignment: messageModel.sender == FirebaseAuth.instance.currentUser!.uid.trim() ? MainAxisAlignment.start : MainAxisAlignment.end,
children: [
Container(
margin: const EdgeInsets.only(bottom: 15.0),
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 15.0),
decoration: BoxDecoration(
color: const Colors.greenAccent,
borderRadius: BorderRadius.circular(15.0)
),
child: Column( // Used expanded property on this, but that didn't work too
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(messageModel.message.toString(), style: GoogleFonts.oswald(color: Colors.white)),
const SizedBox(height: 2.0),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, // not working
children: [
Text(DateFormat.jm().format(messageModel.createdOn!).toString(), style: GoogleFonts.oswald(color: Colors.white, fontSize: 12.0,)),
// also tried to make the use of spacer widget, but that didn't work too
const Icon(CustomIcons.check, color: Colors.white, size: 12.0)
],
)
],
),
)
],
);
I'm trying to keep time and tick icon apart from each other
the problem here is that the row is occupying the least amount of width possible for what it stores inside it, and that is that there is no separation since there is no space available inside the row for said separation, you could do the following to solve this . At least it works for me to handle it that way.
you need to wrap the row in a container to which you assign a min value of width and a max value if you want to anyway. I only left it with minimum value
Container(
constraints: const BoxConstraints(minWidth: 120),
child: Row(
mainAxisAlignment: MainAxisAlignment
.spaceBetween, // not working
mainAxisSize: MainAxisSize.max,
children: [
Text('fecha X',
style: GoogleFonts.oswald(
color: Colors.white,
fontSize: 12.0,
)), // also tried to make the use of spacer widget, but that didn't work too
const Icon(Icons.check,
color: Colors.white, size: 12.0)
],
),
)
For some reason button text gets gray in release mode while being fine in debug mode. Here is the example of how it looks in debug mode:
And this is an example of how it looks like in release mode:
Code for the button is following:
Expanded(
child: Container(
padding: EdgeInsets.all(ScreenUtil().setWidth(40)),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: ScreenUtil().setWidth(263),
height: ScreenUtil().setHeight(69),
padding: EdgeInsets.all(ScreenUtil().setWidth(20)),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.success,
borderRadius: BorderRadius.all(Radius.circular(12.0))),
child: FlatButton(
onPressed: () {
// some actions
},
child: Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget> [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Выбрать", style: TextStyle(color: Theme.of(context).colorScheme.primaryLight, fontSize: ScreenUtil().setSp(16)), textAlign: TextAlign.center),
Container(
padding: EdgeInsets.fromLTRB(ScreenUtil().setWidth(20), 0, 0, 0),
child: SvgPicture.asset("assets/icons/forward.svg", height: ScreenUtil().setHeight(20), width: ScreenUtil().setWidth(20))
),
]
)
],
)
)
)
)
]
)
]
)
)
)
As you can see, I am using ScreenUtil for managing flexible layouts. Suspicion is that it somehow fails to do its job properly.
Can somebody explain what is going on here, why is the perfectly renderable app behaves this way in release mode when no overflows are reported? And, what is more important, how to fix it (preferably without changing font size as it is already small enough)?
I adjusted the code, now it looks like this:
Expanded(
child: Container(
padding: EdgeInsets.all(ScreenUtil().setWidth(40)),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FlatButton(
onPressed: () {
// some actions
},
child: Container(
width: ScreenUtil().setWidth(263),
height: ScreenUtil().setHeight(69),
padding: EdgeInsets.all(ScreenUtil().setWidth(20)),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.success,
borderRadius: BorderRadius.all(Radius.circular(12.0))),
child:
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Выбрать", style: TextStyle(color: Theme.of(context).colorScheme.primaryLight, fontSize: ScreenUtil().setSp(16)), textAlign: TextAlign.center),
Container(
padding: EdgeInsets.fromLTRB(ScreenUtil().setWidth(20), 0, 0, 0),
child: Icon(Icons.arrow_forward, size: 20)
),
]
)
)
)
]
)
)
)
The process of adjustment was rather tedious as long as I had to build release versions to try every change of code on the phone where issue is reproducible (everything is fine on emulator, no gray rectangles reproduce there). First I found minimal code that worked without displaying unwanted gray rectangle and started building up step-by-step from there. Result is working button without unwanted side-effects. To be honest, now when I am able to compare buggy and working solutions, I still don't know what exactly was wrong with previous code sample. Position of FlatButton wrapper didn't matter much, grey rectangle was just bigger if it was moved up the document tree. I guess getting rid of extra Row declaration eventually made it work.
I have this list view in flutter which I am trying to make into a chat list. Similar to what you see in WhatsApp and telegram. However I am struggling to get the idea of how rows and columns work because I keep getting overflows.
Here is the code:
ListView(
physics: BouncingScrollPhysics(),
children: [
Dismissible(
key: Key(""),
background: Container(color: Colors.grey[200]),
direction: DismissDirection.endToStart,
child: InkWell(
onTap: () {},
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Flex(
direction: Axis.vertical,
children: [
Text("Hello"),
],
),
Flex(
direction: Axis.vertical,
children: [
Text(
"al;skdl;aksd a;skd ;aks;dk a;skd ;laks;d a;lsk d;lkas; dka;lsk d;laks; ldka;slk d;a",
overflow: TextOverflow.ellipsis,
maxLines: 2,
),
],
),
],
),
),
),
],
Now we often experience the text overflow problem so if we think it that we we have provided column a particular width and restricted it but if we wrap the things up with flexible widget it now tells column/Row that you can change your size and be flexible
order would be
flexible > Container > Column/Row
The reason we are applying this to container is Column/Row will ask immediate parent for width and height
now this problem can also be solved by text overflow property that is we can clip text but what if we dont want too
So all you have to do is Wrap the column/Row in Container and then into Flexible as now it will tell container that yes you can adjust your height
Your concept can be cleared by how actually widgets parent child relationship works i.e in brief
basically If am a child I will ask my parent okay what is my size so since my parent if it has a size it will bound me but if it doesnt has a size it will ask its parent okay tell me what space should I take and it goes on. Expanded and Flexible says that okay you can adjust yourself instead of being Fixed.
Flexible(
child: Container(
margin: EdgeInsets.only(left: 10.0,right: 10.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('${dataBookTitleSearch1[index]} ', style: kGoodSearchResultTextStyle, textAlign: TextAlign.left,),
SizedBox(
height: 10.0,
),
Text('${dataBookAuthorSearch1[index]}', style: kGoodSearchResultTextStyle,textAlign: TextAlign.left),
SizedBox(
height: 10.0,
),
Text('${dataBookExtensionSearch1[index]} ', style: kGoodSearchResultTextStyle,textAlign: TextAlign.left),
SizedBox(
height: 20.0,
),
Container(
width: 80.0,
height: 40.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
color: Colors.white
),
child: Padding(
padding: const EdgeInsets.only(left:20.0,top: 12.0),
child: Text('Read'),
),
),
],
),
),
)
In the picture below, what I'm trying to achieve, is let the Green part Scrollable, since, in case the keyboard pops up, it doesn't give me the render error.
The whole screen is just a Column, where yellow part is a custom widget, and green part another Column inside it.
I've tried different solutions.
Wrap the whole Column into a SingleChildScrollView, but I would like that yellow part would stay fixed at the top.
I've tried also wrapping only green part into a SingleChildScrollView, but it doesn't work (The Render Error still raised).
I've seen I could use SliverAppBar, but I would like to achieve using my custom widget (yellow part).
I am a little bit stuck.
Scaffold(
body: SafeArea(
child: Column(
children: [
AppBarWidget(height: size.height * 0.15),
Container(
height: size.height - size.height * 0.15 - mediaQuery.padding.top,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
EditableAvatarWidget(
circleRadius: circleRadius,
badge: test,
border: Border.all(color: test.mainColor, width: 5),
),
Column(
children: [
Text(
"Name Surname",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26,
color: Global.blackGrey),
),
SizedBox(height: 10),
Text(
"mail#mail.com",
style: TextStyle(fontSize: 18, color: Colors.grey),
)
],
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width / 6, vertical: 0),
child: FlatCustomButton(
onPress: () {},
background: Global.editProfileButton,
text: "Edit profile",
textColor: Global.blackGrey,
inkwellColor: Colors.black,
),
)
],
),
),
],
),
),
);
I would maybe also think to implement a ListView (?), but as you can see I've set inside the Column the mainAxisAlignment: MainAxisAlignment.spaceAround to have already my UI preference.
Do you have any idea how I could achieve this?
TL;DR: Let scrollable only GreenPart (Column) that belong to another Column (Whole Screen) and let Yellow Part stay on that fixed position
That's how I fixed.
I've encapsulated the Green Column Part in a Expanded before and then into a SingleChildScrollView.
It works exactly how I wanted.
Now only the green part scroll, and the yellow part stays in a fixed position when keyboard appears.
return Scaffold(
body: SafeArea(
child: Column(
children: [
AppBarWidget(
height: size.height * 0.15,
),
Expanded( //This
child: SingleChildScrollView( // and this fixed my issue
child: Container(
height:
size.height - size.height * 0.15 - mediaQuery.padding.top,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
EditableAvatarWidget(
circleRadius: circleRadius,
badge: test,
border: Border.all(color: test.mainColor, width: 5),
),
Column(
children: [
Text(
"Name Surname",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 26,
color: Global.blackGrey),
),
SizedBox(height: 10),
Text(
"mail#mail.com",
style: TextStyle(fontSize: 18, color: Colors.grey),
)
],
),
Padding(
padding: EdgeInsets.symmetric(
horizontal: size.width / 6, vertical: 0),
child: FlatCustomButton(
onPress: () {},
background: Global.editProfileButton,
text: "Edit profile",
textColor: Global.blackGrey,
inkwellColor: Colors.black,
),
)
],
),
),
),
),
],
),
),
);
You can use SliverAppBar like you have already tried, but inside that you have flexibleSpaceBar which has background property that can accept any kind of Widget.
A sample code is here.
If you can set a fixed height to the Column inside the SingleChildScrollView,
that's probably the best, even if it involves a bit of "hacking" as in the fix you provided.
However, when you need flexible/expanding content in the Column, you can consider using a ConstrainedBox with IntrinsicHeight inside the SingleChildScrollView as the SingleChildScrollView's documentation describes.
I've found that for relatively simple screens this works well. E.g. where you really only need scrolling if you have an input field and the keyboard pops up, as in your code.
LayoutBuilder(
builder: (BuildContext context, BoxConstraints viewportConstraints) {
return SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: viewportConstraints.maxHeight,
),
child: IntrinsicHeight(
child: Column(
children: <Widget>[
...
Note: with more complex screens, IntrinsicHeight might be too costly, see its docs for more info.
[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.