Center the trailing icon of expansion tile in Flutter - flutter

I would like to horizontally center the trailing icon of my expansionTile,
Here is my expansionTile with the trailing on the bottom right :
I already tried to encapsulate the Icon in a Align and a Container but doesn't work, I also tried Padding but it's not stable if you change the size of the screen.
Code with Align :
trailing : Align(
alignment: Alignment.center,
child: Icon(
BeoticIcons.clock,
color: BeoColors.lightGreyBlue
)
),
With Container :
trailing: Container(
alignment: Alignment.center,
child: Icon(
BeoticIcons.clock,
color: BeoColors.lightGreyBlue
)
),
Thanks for your help.

This will work for you. Use LayoutBuilder to get parent widget width, and set relative padding using constraints. For example, use constraints.maxWidth * 0.5, to center across width. Your padding will be stable if you change the size of the screen:)
trailing: LayoutBuilder(builder: (ctx, constraints) {
return Padding(
padding: EdgeInsets.only(
right: constraints.maxWidth * 0.5,
),
child: Icon(
Icons.menu,
),
);
}),

you can use column and align your icon like this way hope this code will help you, thank you
import 'package:flutter/material.dart';
class Hello extends StatelessWidget {
const Hello({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 140,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5.0),
color: Colors.deepPurple[200],
),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Center(child: Text("Hello")),
Text("Hello"),
SizedBox(height: 50,),
Align(
alignment: Alignment.center,
child: Icon(Icons.lock_clock))
],
),
),
),
),
),
);
}
}

Ok, I found how to do it.
Simply put the icon in the title attribute of the ExpansionTile :
return ExpansionTile(
title: Icon(
BeoticIcons.simply_down,
color: BeoColors.lightGreyBlue,
),

Related

How To make Responsive Containers with the same sized in flutter

I have a list of strings for tabs, and want to give same width to all tabs instead of based on text length...
Like I have 4 tabs , it should be occupy same width ,
and if text length is bigger than text size should b adjusted..
DONT want to user listview, all tabs should be adjusted according to available width
like width is 300 and tabs are 2, each tab should be in width of 150(including padding etc..)
but I am getting following which I dont want to set widget based on text length
,
class HomeScreen extends StatelessWidget {
HomeScreen({Key? key}) : super(key: key);
List<String> titles=['All','Income','Expense','Debt','Others','Liabilities'];
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
height: 100,
color: Colors.grey,
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: titles.map((e) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 2.0),
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8,vertical: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
),
child: Text(e)),
)).toList(),),
),
),
);
}
}
Wrap each child of Row inside Expanded and Replace Text With AutoSizeText https://pub.dev/packages/auto_size_text
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
final List<String> titles = const [
'All',
'Income',
'Expense',
'Debt',
'Others',
'Liabilities'
];
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
height: 100,
color: Colors.grey,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: titles
.map((e) => Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 2.0),
child: Container(
height: 24,
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 4),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
),
child: AutoSizeText(
e,
maxLines: 1,
textAlign: TextAlign.center,
)),
),
))
.toList(),
),
),
),
);
}
}
Output:
You can achieve this by wrapping each tab in a Container widget with a fixed width and set the mainAxisAlignment property of the parent Row widget to MainAxisAlignment.spaceBetween. This will distribute the tabs evenly across the available width like this.
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
width: 150.0,
child: Text("Tab 1"),
),
Container(
width: 150.0,
child: Text("Tab 2"),
),
Container(
width: 150.0,
child: Text("Tab 3"),
),
Container(
width: 150.0,
child: Text("Tab 4"),
),
],
)
You can adjust the width property of the Container widgets as per your requirements. If the text is larger than the container width, you can adjust the text size using the style property of the Text widget and set the overflow property of the Container widget to TextOverflow.ellipsis to display an ellipsis (...) when the text overflows the container.
Take a look at Boxy, which even has an example of doing what you want to do (make a series of items the width of the largest item).
You can use a LayoutBuilder.
This widget allows you to get the parent's widget width, and according to that you can then use N SizedBox to limit the width of your chips.

I can't display 4 Card in middle of page with Flutter

import 'package:flutter/material.dart';
class CardNote extends StatelessWidget {
const CardNote({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 1',
)),
),
),
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 2',
)),
),
),
],
),
),
),
);
}
}
When I add this widget to the page where I want to show the cards, I can show 2 widgets in a single line. Then when I call the same widget again, I get the following error.
RenderCustomMultiChildLayoutBox object was given an infinite size during layout.This probably means that it is a render object that tries to be as big as possible, but it was put inside another render object that allows its children to pick their own size.
return Scaffold(
body: Container(
child: Row(
children: const [
CardNote(),
SizedBox(
height: 50,
),
CardNote()
],
),
),
);
This is how I add the cards to the page I want to show.
This is how I want to show 4 cards in the middle of the page
This is how it looks on my page. It shows at the top of the page, not in the middle.
You can wrap your CardNote widget with Expanded widget. And use a top level scrollable widget. Also you dont need to us multiple scaffold
home: Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: const [
CardNote(),
SizedBox(
height: 50,
),
CardNote(),
],
),
),
),
While the card is fixed width, you can provide it
class CardNote extends StatelessWidget {
const CardNote({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Center(
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 1',
)),
),
),
Card(
elevation: 3,
color: Colors.amber,
child: SizedBox(
width: 200,
height: 200,
child: Center(
child: Text(
'Card 2',
)),
),
),
],
),
),
);
}
}
You are trying to add a row which has alignment of spaceEven inside another row. When you added the first set of cards it got aligned evenly. On second set you have 2 set of rows inside a row each one has alignment of spaceEven..
Depending on the layout if you wish to show these cards one below the other set then use a Column widget
return Scaffold(
body: Container(
child: Column(//here
children: const [
CardNote(),
SizedBox(
height: 50,
),
CardNote()
],
),
),
);

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:

Multiple buttons/Texts in a circle in flutter

I'm trying to create a circle in the flutter. I want to add multiple buttons and bound them in a circle like this.
The marked fields are supposed to be buttons and Course 1 is just the text.
I am able to create something like this but it is only string splitted in the button.
Here is my code for this. I'm not getting any idea about how to do this task. I'm new to flutter.
import 'package:flutter/material.dart';
void main(){runApp(MyApp());}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: new AppBar(
title: Text("Student home"),
),
body:Center(
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
width: 200,
height: 200,
child: Center(
child: Text("Course 1 \n Course 2",
style: TextStyle(fontSize: 12.0,
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
),
decoration: BoxDecoration(
border:Border.all(width:3),
borderRadius: BorderRadius.all(
Radius.circular(50),
),
color: Colors.yellow,
),
),
)
),
);
}
}
try shape: BoxShape.circle,,
Container(
width: 100,
height: 100,
decoration: BoxDecoration(
border: Border.all(width: 2),
shape: BoxShape.circle,
// You can use like this way or like the below line
//borderRadius: new BorderRadius.circular(30.0),
color: Colors.amber,
),
child:Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('ABC'),
Text('XYZ'),
Text('LOL'),
],
),
),
Output
is this design that you want?
it contain two button and one text widget
body: Center(
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
width: 200,
height: 200,
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
"Course 1",
style: TextStyle(
fontSize: 12.0,
fontStyle: FontStyle.italic,
),
textAlign: TextAlign.center,
),
MaterialButton(
onPressed: () {
//do whatever you want
},
child: Text("Mark Attendance"),
),
MaterialButton(
onPressed: () {
//do whatever you want
},
child: Text("Mark Attendance"),
),
],
),
),
decoration: BoxDecoration(
border: Border.all(width: 3),
borderRadius: BorderRadius.all(
Radius.circular(200),
),
color: Colors.yellow,
),
),
),
There are multiple ways to make the border round. As of now you are using fixed height and width always use greater number for border-radius.
For eg.
when your heigh is 200X200 use 150-200 number for border-radius.
here is the code which works fine when you have fixed height and width of the container.
Note: This works only fine when your heigh and width is fixed for the container because the padding in the code is static.If you want dynamic then please use the screen calculation techniques to make if responsive
Making any widget clickable in the Flutter.
There are a couple of Widgets available to make any widget clickable
Gesture Detector
This widget has many methods including onTap() which means you can attach a callback when the user clicks on the widget. For eg (this is used in your code)
GestureDetector(
onTap: (){}, //this is call back on tap
child: Text("Mark Attendance")
)
InkWell Widget (Note: This widget will only work when it is a child of the Material widget)
Material(
child: InkWell(
onTap: (){},
child: Text("Mark Attendance"),
),
)
Here is the working code.
import 'package:flutter/material.dart';
void main(){runApp(MyApp());}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: new AppBar(
title: Text("Student home"),
),
body:Center(
child: Container(
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
width: 200,
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(bottom:40.0,top: 20.0),
child: Text("Course 1"),
),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: (){},
child: Text("Mark Attendance")),
),
Padding(
padding: const EdgeInsets.all(8.0),
child:Material(
child: InkWell(
onTap: (){},
child: Text("Mark Attendance"),
),
)
),
],)
],
),
decoration: BoxDecoration(
border:Border.all(width:3),
borderRadius: BorderRadius.all(
Radius.circular(150),
),
color: Colors.yellow,
),
),
)
),
);
} }
Note: Material widget always set the background as white for the text
widget
Thanks, I hope is information was helpfull

How to remove Padding from DrawerHeader

Here's my DrawerHeader :
class MyDrawerHeader extends StatefulWidget {
#override
_MyDrawerHeaderState createState() => _MyDrawerHeaderState();
}
class _MyDrawerHeaderState extends State<MyDrawerHeader> {
#override
Widget build(BuildContext context) {
return DrawerHeader(
padding: EdgeInsets.all(0),
margin: EdgeInsets.all(0),
child: Center(child: Text('Header', style: Theme.of(context).textTheme.headline))
);
}
}
As you can see I made the Padding and Margin from the DrawerHeader be 0, but this is how my Header is being shown:
It's just too big and I can't make it smaller. I have no idea why its being rendered this way, I looked into DrawerHeader source code and I can't see anything in there overriding my Padding or Margin.
Just to be sure the problem is in DrawerHeader, this is what Happens when I substitute it for a Container:
It works as it should!
Am I missing something, or is this a bug in Flutter?
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
padding: EdgeInsets.all(0.0),
child: Container(
color: Theme.of(context).primaryColor,
),
),
ListTile(
title: Text("Home"),
)
],
),
),
There is always padding on DrawerHeader. If you look in sources:
#override
Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context));
assert(debugCheckHasMediaQuery(context));
final ThemeData theme = Theme.of(context);
final double statusBarHeight = MediaQuery.of(context).padding.top;
return Container(
height: statusBarHeight + _kDrawerHeaderHeight,
margin: margin,
decoration: BoxDecoration(
border: Border(
bottom: Divider.createBorderSide(context),
),
),
child: AnimatedContainer(
padding: padding.add(EdgeInsets.only(top: statusBarHeight)),
decoration: decoration,
duration: duration,
curve: curve,
child: child == null ? null : DefaultTextStyle(
style: theme.textTheme.body2,
child: MediaQuery.removePadding(
context: context,
removeTop: true,
child: child,
),
),
),
);
}
You can customize this code:
height: statusBarHeight + _kDrawerHeaderHeight - here is total height of header
padding: padding.add(EdgeInsets.only(top: statusBarHeight)) - here is padding of child element in DrawerHeader
Try replacing your drawer by the code below
drawer: Drawer(
child: DrawerHeader(
child: ListView(
children: <Widget>[
Container(
alignment: Alignment.topLeft,
child: Text('Header', style: Theme.of(context).textTheme.headline),
),
],
),
),
),