Give my round image a matching border in flutter - flutter

I have this button in my app to change the language, and the button's icon is a round flag representing whatever language is currently selected. To make the user understand it's a button, I want to give it a little border so I looks more like a button, but I can't find a way to make the border round to match the icon.
So far, the best I can do is add a decoration to the icon with rounded corner, but it doesn't work. Here's the result and the code, any help is appreciated ! (I wonder if there is a solution that would adapt to the form of the image, if I change my mind a decide to use a rectangle image or a flag shaped, emoji type image. Thanks!)
return Padding(
padding: const EdgeInsets.all(10),
child: DropdownButton(
onChanged: (Language? lang) {
lang == null ? print("Null language error") : _changeLanguage(lang.languageCode);
},
underline: SizedBox(),
icon: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.blueGrey,
),
child: buttonIcon),
items: ...,
),
);

You could increase the radius of your BorderRadius to match the radius of the buttonIcon and give buttonIcon some padding.
Something like this:
return Padding(
padding: const EdgeInsets.all(10),
child: DropdownButton(
onChanged: (Language? lang) {
lang == null ? print("Null language error") : _changeLanguage(lang.languageCode);
},
underline: SizedBox(),
icon: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(200), // you can adjust this value to your needs
color: Colors.blueGrey,
),
child: Padding(
padding: const EdgeInsets.all(10), // this value will be the width of your border
child: buttonIcon,
),
),
items: ...,
),
);

Solution given by Chirag Bargoojar in the comments.
What I did was create a CircleAvatar and give it another Circle avatar as a child, the first one creates the outer ring that works as the border.
Result:
Code:
icon: CircleAvatar(
radius: 22,
backgroundColor: Colors.blueGrey,
child: CircleAvatar(
backgroundImage: buttonIcon,
radius: 18,
),
),
I'm still going to look for the best possible color, but it does look pretty good this way!

Related

Can't center Icon in a TextButton

I'm trying to center the minimized icon in this Icon Button but can't get it to work:
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(
height: 25,
child: TextButton(
onPressed: appWindow.minimize,
style: const ButtonStyle(
alignment: Alignment.center,
padding: MaterialStatePropertyAll(EdgeInsets.all(0))),
child: const Icon(
Icons.minimize,
color: Colors.white,
),
),
),
TextButton(
onPressed: maximizeOrRestore,
child: Icon(
appWindow.isMaximized ? Icons.fullscreen_exit : Icons.fullscreen,
color: Colors.white,
)),
TextButton(
onPressed: appWindow.close,
child: const Icon(
Icons.close,
color: Colors.white,
),
)
],
);
}
I'm expecting the button to be centered and as you can see i've already tried using alignment and padding
When you say "center the minimized icon", do you mean that this icon should be between the other two icons? In that case, you just need to switch the first two widgets in the Row widget's children.
But I think you want the minimize icon to be higher so that it's something like-> - ◾️ X
If this is what you want then you can't use Icons.minimize. If you check out this icon on this page, you will notice that the minimize icon looks like an underscore. This is by design. I think this looks good, but if you insist on having a minus sign kind of symbol then you can use Icons.remove_rounded.
It's not that the icon is not centered, the Material minimize icon has blank space in the upper size, because it is suppose to be down to understand that is a minimize button just like the maximize button has blank space in the bottom size. What you can try is to use a different icon if you really want it to be centered. Try with Icons.horizontal_rule.
You can use CupertinoIcons.minus like
TextButton(
onPressed: appWindow.minimize,
child: const Icon(
CupertinoIcons.minus,
color: Colors.white,
),
),

why the text inside the container does not show flutter

hello i'm new in flutter so inside a column a container then a sized box then another container and finally a button . the problem is the container which have the color amber does not show despite print is worked but i don't see the container on my screen . i wanna display a text inside that container if the email invalid any help ! thanks in advise
Container(
height: MediaQuery.of(context).size.height * 0.08,
margin: const EdgeInsets.symmetric(horizontal: 5),
decoration: BoxDecoration(
color: const Color(0xFFEFEDED),
border: Border.all(color: Colors.transparent),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.only(left: 8.0),
child: TextFormField(
controller: emailController,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
border: InputBorder.none,
),
),
),
),
const SizedBox(
height: 50,
),
InkWell(
onTap: () {
if (isValidEmail) {
emailsList.add(emailController.text);
box.write('emails', emailsList);
Navigator.of(context).pop();
}
if (!isValidEmail) {
Row(
children: [
Container(
color: Colors.amber,
),
],
);
print("test");
}
},
child: CustomButton("Ajouter", buttonColor, Colors.white)),
First of all, if you do not give any height or width to your container but only a color, it will never show. Why? Because it has no content meaning that the height and width by default are 0. So, I advise setting a height and width first.
Second, if you want to display a text if the field is not valid, you have something already existing. In your textField, you can give him an Inputdecoration and there you can access the parameters errorText. In order to have this working, you must use the formValidation with the widget Form and you kive him a key that is a formValidator.
Finally, if you do not want to use the errorText by default, you should put in the column something like this.
Column(
children:[
TextField(),
if (isEmailInvalid)
Text("This is the error Text")
]
)
With the "isEmailInvalid" which is a boolean.
I hope that all this information helps you. But if you have really a beginner, I advise to stick with the default setting of the TextField and take a look at the flutter documentation that is really interesting.
put a Row in Inkwell onTap? Row is not a function, you must return it in your build method.
return type of if statement must be 'Widget' . use 'return' before Container widget.

Multi-line flutter text field occupies all of Flexible space with ugly right padding

I'm building chat bubbles in a flutter app and it's triggered my inner perfectionist. The main code for displaying an incoming message from another chat user is:
Widget getOtherUserMessageRow() {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
message.cm.senderIsSameAsPreviousOnSameDay(AppState.i.activeUserId)
? SizedBox(width: AppState.i.chatItemOtherUserLeftInset) // If sender is previous message sender on same day, don't repeat avatar
: message.getCreatorAvatar(),
SizedBox(width: AppState.i.chatItemOtherUserAvatarRightPadding), // Leave fixed gap for other messages
Flexible(
fit: FlexFit.loose,
child: message.cm.messageType.getMessageWidget(message),
),
SizedBox(width: AppState.i.chatItemOtherUserMessageRightPadding), // Fixed gap for non-user messages
],
);
}
Then we have the code that creates the bubble, indirectly called via message.cm.messageType.getMessageWidget(message):
Widget build(BuildContext context) {
bool isFromAppUser = message.cm.isFromAppUser(AppState.i.activeUserId);
return Container(
padding: EdgeInsets.symmetric(
vertical: AppState.i.chatItemMessageVerticalInset),
child:
Container(
decoration: BoxDecoration(
color: isFromAppUser ? AppState.i.chatItemUserMessageBackgroundColour : Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(isFromAppUser ? AppState.i.chatItemMessageBorderRadius : 0),
topRight: Radius.circular(isFromAppUser ? 0 : AppState.i.chatItemMessageBorderRadius),
bottomRight: Radius.circular(isFromAppUser ? AppState.i.chatItemMessageCurvedBorderRadius : AppState.i.chatItemMessageBorderRadius),
bottomLeft: Radius.circular(isFromAppUser ? AppState.i.chatItemMessageBorderRadius : AppState.i.chatItemMessageCurvedBorderRadius),
),
boxShadow: [
BoxShadow(
color: AppState.i.chatItemMessageBoxShadowColour,
spreadRadius: AppState.i.chatItemMessageBoxShadowSpreadRadius,
blurRadius: AppState.i.chatItemMessageBoxShadowBlurRadius,
offset: AppState.i.chatItemMessageBoxShadowOffset, // changes position of shadow
),
],
),
padding: EdgeInsets.symmetric(
vertical: AppState.i.chatItemMessageVerInset,
horizontal: AppState.i.chatItemMessageHorInset),
child: Text(
message.cm.messageText,
style: TextStyle(
fontSize: AppState.i.chatItemMessageTextFontSize,
color:
isFromAppUser ? AppState.i.chatItemMessageUserTextFontColour : AppState.i.chatItemMessageOtherUserTextFontColour,
)
),
),
);
}
So what I get is this...
Single line - works fine doesn't use all horizontal space.
Multi-line - uses all available horizontal space up to the sized box on the right with ugly right-hand-side wrapping:
Multi-line another (bad) example:
So what I really want is this:
Any ideas? I'm kinda thinking it's not possible because the TextField would have to intelligently adjust the horizontal fit based on it's internal wrapping. But I'm willing to be proven otherwise by you layout gurus :-)
Are you looking for Paragraph.longestLine property?
Text(
textWidthBasis: TextWidthBasis.longestLine,
...
)

How do I remove Flutter IconButton big padding?

I want to have a row of IconButtons, all next to each other, but there seems to be pretty big padding between the actual icon, and the IconButton limits. I've already set the padding on the button to 0.
This is my component, pretty straightforward:
class ActionButtons extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
color: Colors.lightBlue,
margin: const EdgeInsets.all(0.0),
padding: const EdgeInsets.all(0.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
IconButton(
icon: new Icon(ScanrIcons.reg),
alignment: Alignment.center,
padding: new EdgeInsets.all(0.0),
onPressed: () {},
),
IconButton(
icon: new Icon(Icons.volume_up),
alignment: Alignment.center,
padding: new EdgeInsets.all(0.0),
onPressed: () {},
)
],
),
);
}
}
I want to get rid of most of the light blue space, have my icons start earlier on the left, and closer to each other, but I can't find the way to resize the IconButton itself.
I'm almost sure this space is taken by the button itself, 'cause if I change their alignments to centerRight and centerLeft they look like this:
Making the actual icons smaller doesn't help either, the button is still big:
thanks for the help
Simply pass an empty BoxConstrains to the constraints property and a padding of zero.
IconButton(
padding: EdgeInsets.zero,
constraints: BoxConstraints(),
)
You have to pass the empty constrains because, by default, the IconButton widget assumes a minimum size of 48px.
Two ways to workaround this issue.
Still Use IconButton
Wrap the IconButton inside a Container which has a width.
For example:
Container(
padding: const EdgeInsets.all(0.0),
width: 30.0, // you can adjust the width as you need
child: IconButton(
),
),
Use GestureDetector instead of IconButton
You can also use GestureDetector instead of IconButton, recommended by Shyju Madathil.
GestureDetector( onTap: () {}, child: Icon(Icons.volume_up) )
It's not so much that there's a padding there. IconButton is a Material Design widget which follows the spec that tappable objects need to be at least 48px on each side. You can click into the IconButton implementation from any IDEs.
You can also semi-trivially take the icon_button.dart source-code and make your own IconButton that doesn't follow the Material Design specs since the whole file is just composing other widgets and is just 200 lines that are mostly comments.
Wrapping the IconButton in a container simply wont work, instead use ClipRRect and add a material Widget with an Inkwell, just make sure to give the ClipRRect widget enough border Radius 😉.
ClipRRect(
borderRadius: BorderRadius.circular(50),
child : Material(
child : InkWell(
child : Padding(
padding : const EdgeInsets.all(5),
child : Icon(
Icons.favorite_border,
),
),
onTap : () {},
),
),
)
Instead of removing a padding around an IconButton you could simply use an Icon and wrap it with a GestureDetector or InkWell as
GestureDetector(
ontap:(){}
child:Icon(...)
);
Incase you want the ripple/Ink splash effect as the IconButton provides on click wrap it with an InkWell
InkWell(
splashColor: Colors.red,
child:Icon(...)
ontap:(){}
)
though the Ink thrown on the Icon in second approach wont be so accurate as for the IconButton, you may need to do some custom implementation for that.
Here's a solution to get rid of any extra padding, using InkWell in place of IconButton:
Widget backButtonContainer = InkWell(
child: Container(
child: const Icon(
Icons.arrow_upward,
color: Colors.white,
size: 35.0,
),
),
onTap: () {
Navigator.of(_context).pop();
});
I was facing a similar issue trying to render an Icon at the location the user touches the screen. Unfortunately, the Icon class wraps your chosen icon in a SizedBox.
Reading a little of the Icon class source it turns out that each Icon can be treated as text:
Widget iconWidget = RichText(
overflow: TextOverflow.visible,
textDirection: textDirection,
text: TextSpan(
text: String.fromCharCode(icon.codePoint),
style: TextStyle(
inherit: false,
color: iconColor,
fontSize: iconSize,
fontFamily: icon.fontFamily,
package: icon.fontPackage,
),
),
);
So, for instance, if I want to render Icons.details to indicate where my user just pointed, without any margin, I can do something like this:
Widget _pointer = Text(
String.fromCharCode(Icons.details.codePoint),
style: TextStyle(
fontFamily: Icons.details.fontFamily,
package: Icons.details.fontPackage,
fontSize: 24.0,
color: Colors.black
),
);
Dart/Flutter source code is remarkably approachable, I highly recommend digging in a little!
A better solution is to use Transform.scale like this:
Transform.scale(
scale: 0.5, // set your value here
child: IconButton(icon: Icon(Icons.smartphone), onPressed: () {}),
)
You can use ListTile it gives you a default space between text and Icons that would fit your needs
ListTile(
leading: Icon(Icons.add), //Here Is The Icon You Want To Use
title: Text('GFG title',textScaleFactor: 1.5,), //Here Is The Text Also
trailing: Icon(Icons.done),
),
I like the following way:
InkWell(
borderRadius: BorderRadius.circular(50),
onTap: () {},
child: Container(
padding: const EdgeInsets.all(8),
child: const Icon(Icons.favorite, color: Colors.red),
),
),
enter image description here
To show splash effect (ripple), use InkResponse:
InkResponse(
Icon(Icons.volume_up),
onTap: ...,
)
If needed, change icons size or add padding:
InkResponse(
child: Padding(
padding: ...,
child: Icon(Icons.volume_up, size: ...),
),
onTap: ...,
)

How do I add margins to my widget ? Understanding the effect of EdgeInsets

I am trying to wrap my head around ui placement in Flutter. So I currently have something that looks like this
I would like to add a little space b/w search Textfield and the button.
This is what the controlling part of my code looks like. I am trying to style my textFieldSearchBox so it has a little margin on the right, I tried trying to increase the Edge insets but it seems to increase the size of the TextField I don't know why? I know I could adding a padding element after TextField but I wanted to know what my other options are.Why does increasing the EdgeInsets in the decoration of textFieldSearchBox increase the size of the textbox? My ideal situation would be to add margin around all the borders of this textbox (LTRB).
Any suggestions?
TextField textFieldSearchBox = new TextField(
keyboardType: TextInputType.text,
controller: filterController,
autofocus: false,
decoration: new InputDecoration(
contentPadding: new EdgeInsets.fromLTRB(20.0, 10.0, 100.0, 10.0),
border:
new OutlineInputBorder(borderRadius: BorderRadius.only()),
),
);
var optionRow = new Row(
children: <Widget>[
new Expanded(child:textFieldSearchBox),
searchButton,
new IconButton(
icon: new Icon(Icons.filter),
onPressed: (){print("Called....");},
),
],
);
return new Scaffold(
appBar: new AppBar(
title: new Text("Title goes here.."),
backgroundColor: Colors.lightBlueAccent,
),
body: new Container(
child:new Column(
children: <Widget>[
optionRow,
],
),
),
);
How to add margin to a widget
In Flutter we generally talk about adding Padding around a widget rather than margin. The Container widget does have a margin parameter, but even this just wraps it child (and any decoration that the child has) with a Padding widget internally.
So if you have something like this
and you want to add some space around the widget like this
then you just wrap the widget with Padding. This is easy to do if you put your cursor on the widget name and press Alt+Enter (or Option+Return on a Mac) in Android Studio. Then choose Add padding from the menu.
which gives you something like this
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"text",
style: TextStyle(fontSize: 20.0),
),
);
Meaning of EdgeInsets
When you are setting padding you can't directly use an integer or double. You have to specify the space (number of logical pixels) using the EdgeInsets. You can set all of the sides at once (as we saw in the example above), or you can set them individually like this:
Widget myWidget() {
return Padding(
padding: const EdgeInsets.only(
left: 40,
top: 20,
right: 40,
bottom: 20,
),
child: Text("text"),
);
}
Since in this example left and right are the same and top and bottom are the same, we can simplify EdgeInsets to
padding: const EdgeInsets.symmetric(
horizontal: 40,
vertical: 20,
),
Using a Container to set padding and margin
An alternate method is to wrap your widget in a Container. The Container widget has both a padding and a margin property. (This would only be necessary, though, if you were also adding a decoration like background color or a border.)
Widget myWidget() {
return Container(
margin: EdgeInsets.all(30),
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.yellow,
border: Border.all(color: Colors.black),
),
child: Text(
"Flutter",
style: TextStyle(
fontSize: 50.0
),
),
);
}
Why does increasing the EdgeInsets in the decoration of textFieldSearchBox increase the size of the textbox ?
Because that padding is used for the internal padding. The one you see between the borders and the actual text.
My ideal situation would be to add margin around all the borders of this textbox (LTRB). Any suggestions ?
Wrap your TextField into a Padding. That is the ideal way to achieve the desired layout in flutter.
final textFieldSearchBox = new Padding(
padding: const EdgeInsets.only(right: 8.0),
child: new TextField(
keyboardType: TextInputType.text,
controller: filterController,
autofocus: false,
decoration: new InputDecoration(
contentPadding: new EdgeInsets.fromLTRB(20.0, 10.0, 100.0, 10.0),
border: new OutlineInputBorder(borderRadius: BorderRadius.only()),
),
),
);
You can put the component inside a padding, like this
var optionRow = new Row(
children: <Widget>[
new Expanded(child:textFieldSearchBox),
new Padding(padding: new EdgeInsets.all(20.0),child:button,),
new IconButton(
icon: new Icon(Icons.filter),
onPressed: (){print("Called....");},
),
],
);
Since the layout of your widgets is Row, why do not you add the mainAxisAlignment property to it like this:
mainAxisAlignment : MainAxisAlignment.spaceAround
Or
mainAxisAlignment : MainAxisAlignment.spaceBetween
Simply use
EdgeInsets.fromLTRB
For example:
padding: EdgeInsets.fromLTRB(10.0, 10.0, 10.0, 10.0),
You can also use SizedBox if you want to avoid using Container
There are some widgets which allow that using a parameter, but in most cases You can wrap the Widget in a Padding widget like so.
From this
YourWidget(
....
)
To This
Padding(
padding: EdgeInsets.all(value),
YourWidget(
....
)
)
Where "all" can be replaced with the variant of your choice
In Flutter we generally talk about adding Padding around a widget rather than margin. The Container widget does have a margin parameter, but even this just wraps it child (and any decoration that the child has) with a Padding widget internally.strong text