I have nested rows using this code:
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Row(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'the text in the first row',
),
],
),
Row(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'the text in the second row',
),
],
),
],
)
When there is space, I want the rows to be side by side (current behavior):
Currently, when it overflows, the text gets cut off like this:
Is there a way to force the second row onto a new line when there's no space, so it looks like this?
Try this! It worked for me.
new Flexible(child: new Text('Auto wrap'))
Something on these lines will work:
Wrap(
direction: Axis.horizontal,
children: <Widget>[
Wrap(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'the text ',
),
],
),
Wrap(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'more the text in the first row',
),
],
),
Wrap(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'the text in the second row',
),
],
),
Wrap(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'more text in the second row',
),
],
),
Wrap(
children: <Widget>[
Icon(Icons.fiber_manual_record),
Text(
'the text in the third row',
),
],
),
],
)
Row(
children: [
Checkbox(
onChanged: (bool value) {},
value: true,
),
Flexible(
child: RichText(
strutStyle: StrutStyle(height: 1.4),
softWrap: true,
text: TextSpan(style: TextStyle(fontSize: 12, color: ColorUtil.hexToColor("#999999")), children: <InlineSpan>[
TextSpan(text: "ฉันได้อ่านและยอมรับ "),
TextSpan(text: "ฉันได้อ่านและยอมรับ "),
TextSpan(
text: "สัญญาการให้บริการ & ข้อตกลงความเป็นส่วนตัว",
style: TextStyle(color: ColorUtil.hexToColor("#666666")),
recognizer: TapGestureRecognizer()
..onTap = () {
Navigator.pushNamed(context, "/profile/terms_policy");
}),
]),
),
)
],
),
this work for me. Wrap with Flexible
If you wrapped Text widget with Padding adding Flexible around Padding do the trick.
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
Icons.check,
color: Colors.green,
),
SizedBox(
width: 16,
),
Flexible(
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 8, 0, 0),
child: Text(
'Some text',
style: TextStyle(
fontSize: 18, color: Colors.white),
),
),
),
],
),
Related
I want to know how to swipe down on a page to start the pop animation, but I want the animation to play as we're swiping down. For exemple, the "swipe from left to right" on iOS to pop a page is amazing, because the page that will pop follows the finger swiping LTR. And I want to do the same but vertically, and we would be able to close it from anywhere in the scaffold (not necessarily from the top edge). My animation has an hero animation so it might be harder.
Here's how it looks now :
And I want to have this animation playing, but swiping down, not swiping from the left. (Like exactly this animation, or one where the page goes down).
Here is the page I want to swipe to close :
class TreeDescription extends StatelessWidget {
Tree tree;
bool goBackArrow;
TreeDescription(this.tree, {this.goBackArrow = true});
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onVerticalDragStart: (details) => print("Do something"),
child: Column(
children: <Widget>[
Stack(
children: [
Hero(
transitionOnUserGestures: true,
tag: tree.imagePath,
child: Container(
height: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black, Colors.transparent],
begin: Alignment.bottomCenter,
end: Alignment.topCenter,
stops: [0, 0.2]
),
borderRadius: BorderRadius.only(bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
image: DecorationImage(image: AssetImage(tree.imagePath), fit: BoxFit.cover),
),
child: Align(
alignment: Alignment.bottomCenter,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text(
tree.name,
style: Theme.of(context)
.textTheme
.headline4
.copyWith(fontWeight: FontWeight.w600, color: Colors.white),
),
Text(
tree.species,
style: Theme.of(context)
.textTheme
.headline6
.copyWith(fontWeight: FontWeight.w600, color: Colors.white),
),
],
),
),
),
),
goBackArrow ? Positioned(
top: 30,
child: IconButton(
icon: Icon(Icons.chevron_left, color: Colors.white, size: 40,),
onPressed: () => Navigator.pop(context),
tooltip: 'Retour',
),
) : SizedBox.shrink()
],
),
Expanded(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text("Description :", style: Theme.of(context).textTheme.headline6.copyWith(color: Theme.of(context).primaryColor),),
Text(tree.description, textAlign: TextAlign.justify,),
SizedBox(height: 20,),
Text("La feuille du ${tree.name.toLowerCase()} :", style: Theme.of(context).textTheme.headline6.copyWith(color: Theme.of(context).primaryColor),),
SizedBox(height: 5,),
Row(
children: [
Container(
width: MediaQuery.of(context).size.width/2-40,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset(tree.leafImagePath)
),
),
SizedBox(width: 5,),
Expanded(
child: Text(tree.leafDescription, textAlign: TextAlign.justify,)
),
],
),
],
),
),
),
)
],
),
),
);
}
}
I need to design something like an alert view for display password policy. But I don't know how to design like this. If press button view this kind of alert?
My design and code
viewPolicy() {
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Password Policy"),
content: Container(
width: 10.0,
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Text(
"Minimum Password Length : ${widget.minPwdlength}"),),],),
Row(
children: <Widget>[
Expanded(
child:
Text("Minimum Password Uppercase Characters : 1"),),],),
Row(
children: <Widget>[
Expanded(
child:
Text("Minimum Password lowercase Characters : 1"),),],),
Row(
children: <Widget>[
Expanded(
child: Text("Minimum Password Numeric Characters : 1"),),],),
Row(
children: <Widget>[
Expanded(
child: Text("Minimum Special Characters : 1"),),], ),
Row(
children: <Widget>[
Expanded(
child: Text(
"Allowed Characters : ! # # \$ & * ~ Password cannot contain spaces",
style: TextStyle(color: Colors.grey),
),),], ),], ), ),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text(
"OK",
style: TextStyle(fontWeight: FontWeight.bold),
))], ); });}
I need to design like this,
Here is the code, hope it will be helpful.
Screenshot
Dialog errorDialog = Dialog(
//this right here
child: Theme(
data: ThemeData().copyWith(
inputDecorationTheme: InputDecorationTheme(
border: OutlineInputBorder(),
),
),
child: Container(
color: Colors.blueGrey[100],
height: MediaQuery.of(context).size.height / 3.5,
width: MediaQuery.of(context).size.width / 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Minimum Password Length"),
Text(": 6")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Minimum Password Uppercase Characters"),
Text(": 1")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Minimum Password lowercase Characters"),
Text(": 1")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Minimum Password Numeric Characters"),
Text(": 1")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("Minimum Special Characters"),
Text(": 1")
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
"Allowed Characters:\n! # # \$ & * ~\nPassword cannot contain spaces",
style: TextStyle(color: Colors.grey[700]),
),
),
],
),
),
// you can remove this Row if you don't want the ok button, the user can dismiss the dialog by pressing anywhere in the screen.
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FlatButton(
child: Text(
"Ok",
style: TextStyle(fontWeight: FontWeight.bold),
),
onPressed: () => Navigator.of(context).pop(),
)
],
)
],
),
),
),
),
);
showDialog(
context: context,
builder: (BuildContext context) => errorDialog);
I have a card that contains row of items (text and checkbox widgets). The problem is that the card can only fill up limited space each row, but it isn't going to the next line in the row. I tried using the wrap widget but it had no effect. I keep getting this:
As you can see it is not wrapping to the next but trying to fit everything in that one line. Here is my code:
Widget _buildCategories() {
return Card(
margin: const EdgeInsets.only(top: 20.0),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Text(
'Categories',
style: TextStyle(fontFamily: 'MonteSerrat', fontSize: 16.0),
),
Wrap(
children: <Widget>[
Row(
children: <Widget>[
_checkBox('Gaming'),
_checkBox('Sports'),
_checkBox('Casual'),
_checkBox('21 +'),
_checkBox('Adult'),
_checkBox('Food'),
_checkBox('Club'),
_checkBox('Activities'),
_checkBox('Shopping'),
],
)
],
)
],
),
));
}
Widget _checkBox(String category) {
return Expanded(
child: Column(
children: <Widget>[
Text(
'$category',
textAlign: TextAlign.center,
style: TextStyle(fontFamily: 'MonteSerrat'),
),
Checkbox(
value: false,
onChanged: (value) {
// We will update the value to the firebase data here
print('updated value to: $value');
},
)
],
));
}
I fixed your code with the following changes:
Removed Row widget inside Wrap.
Removed Expanded widget.
Add the property maxLines to your Text widget.
Widget _buildCategories() {
return Card(
margin: const EdgeInsets.only(top: 20.0),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Text(
'Categories',
style: TextStyle(fontFamily: 'MonteSerrat', fontSize: 16.0),
),
Wrap(
children: <Widget>[
_checkBox('Gaming'),
_checkBox('Sports'),
_checkBox('Casual'),
_checkBox('21 +'),
_checkBox('Adult'),
_checkBox('Food'),
_checkBox('Club'),
_checkBox('Activities'),
_checkBox('Shopping')
],
)
],
),
));
}
Widget _checkBox(String category) {
return Column(
children: <Widget>[
Text(
'$category',
maxLines: 1,
textAlign: TextAlign.center,
style: TextStyle(fontFamily: 'MonteSerrat'),
),
Checkbox(
value: false,
onChanged: (value) {
// We will update the value to the firebase data here
print('updated value to: $value');
},
)
],
);
}
}
Also you can add the properties runSpacing and spacing to your Wrap widget to give more space between your items in horizontal and vertical.
Wrap(
runSpacing: 5.0,
spacing: 5.0,
More info here: https://api.flutter.dev/flutter/widgets/Wrap-class.html
Following this link Add a Drawer to a screen I have created a drawer.
Following is my piece of code:
// FUNCTION CONTAINING LEFT SIDE MENU ITEMS
_drawerList() {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'John Doe',
),
],
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/menu_bg.png'),
fit: BoxFit.cover,
),
),
),
ListTile(
// Some Code
),
],
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
// Some Code
drawer: Drawer(
child: _drawerList(),
),
// Some Code
}
}
Is there any way I can fix "DrawerHeader" so that it doesn't move with the drawer and list view.
P.S. I don't want to hold ListView. I just want to hold or fix "DrawerHeader".
Yes, move it out of the ListView widget and use Column to hold both DrawerHeader and ListView.
With items scrolling enabled
_drawerList() {
return Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DrawerHeader(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'John Doe',
),
],
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/menu_bg.png'),
fit: BoxFit.cover,
),
),
),
ListView(
padding: EdgeInsets.zero,
children: <Widget>[
ListTile(
// Some Code
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
],
),
],
),
);
}
With items scrolling disabled
_drawerList() {
return Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DrawerHeader(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'John Doe',
),
],
),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/menu_bg.png'),
fit: BoxFit.cover,
),
),
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
ListTile(
// Some Code
),
],
),
);
}
Instead of wrapping inside ListView you can wrap it inside column and then add other widget inside that. Also if you want to divide header and other part in any ratio you can use Expanded widget.
_drawerList() {
return Drawer(
child: Container(
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: DrawerHeader(
padding: EdgeInsets.all(0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'John Doe',
),
],
),
),
),
Expanded(
flex: 2,
child: ListView(
scrollDirection: Axis.vertical,
children: <Widget>[
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
ListTile(
title: Text("Ses"),
// Some Code
),
],
),
)
],
),
),
);
}
I use this code to pin DrawerHeader on top with fixed height and make list to fill rest of space below.
final drawer = Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
height: 200,
child: DrawerHeader(
decoration: BoxDecoration(color: Colors.blue),
child: Text('Right Drawer Header',
style: TextStyle(color: Colors.white, fontSize: 24)))),
Expanded(
child: ListView(padding: EdgeInsets.zero, children: [
ListTile(leading: Icon(Icons.message), title: Text('Message')),
ListTile(
leading: Icon(Icons.account_circle), title: Text('Profile')),
ListTile(leading: Icon(Icons.settings), title: Text('Settings')),
]))
]));
I'm trying to have a Widget align to the bottom of my NavDrawer while still keeping a DrawerHeader and a list at the top of the Drawer. Here's what I'm trying:
drawer: new Drawer(
child: new Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Text('Top'),
new Align(
alignment: FractionalOffset.bottomCenter,
child: new Text('Bottom'),
),
],
),
),
The bottom text should be aligned to the bottom of the drawer, but It isn't!
You need to wrap your Align widget in Expanded.
drawer: Drawer(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Text('Top'),
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Text('Bottom'),
),
),
],
),
),
Edit:
Years on and there's a much easier solution:
return Drawer(
child: Column(
children: [
ListView(), // <-- Whatever actual content you want goes here
Spacer(), // <-- This will fill up any free-space
// Everything from here down is bottom aligned in the drawer
Divider(),
ListTile(
title: Text('Settings'),
leading: Icon(Icons.settings),
),
ListTile(
title: Text('Help and Feedback'),
leading: Icon(Icons.help),
),
]
);
A little late to the party, but here's my solution to this problem:
#override
Widget build(BuildContext context) {
return Drawer(
// column holds all the widgets in the drawer
child: Column(
children: <Widget>[
Expanded(
// ListView contains a group of widgets that scroll inside the drawer
child: ListView(
children: <Widget>[
UserAccountsDrawerHeader(),
Text('In list view'),
Text('In list view too'),
],
),
),
// This container holds the align
Container(
// This align moves the children to the bottom
child: Align(
alignment: FractionalOffset.bottomCenter,
// This container holds all the children that will be aligned
// on the bottom and should not scroll with the above ListView
child: Container(
child: Column(
children: <Widget>[
Divider(),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings')),
ListTile(
leading: Icon(Icons.help),
title: Text('Help and Feedback'))
],
)
)
)
)
],
),
);
}
This produces the below output where the UserAccountDrawerHeader and the text items can be scrolled around inside the drawer but the Divider and the two ListTiles stay static on the bottom of the drawer.
look whats the problem with your code you have added a Column as a Child to the Drawer so whatever you add in it are vertically placed and The height of Column is by default shrunk to its children's height and it gets larger as the child gets, so there's no point in adding an Align inside a Column
The Simpler Solution Would be to use an Expanded Widget that takes the remaining Space Look I have used a Column and added A widget above and below the Expanded Widget.
Drawer(
elevation: 1.5,
child: Column(children: <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.redAccent,
)),
Expanded(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
ListTile(
title: Text('My Cart'),
leading: Icon(Icons.shopping_cart),
onTap: () {},
),
ListTile(
title: Text('My Orders'),
leading: Icon(Icons.add_shopping_cart),
onTap: () {},
),
ListTile(
title: Text('Logout'),
leading: Icon(Icons.exit_to_app),
onTap: () {})
],
)),
Container(
color: Colors.black,
width: double.infinity,
height: 0.1,
),
Container(
padding: EdgeInsets.all(10),
height: 100,
child: Text("V1.0.0",style: TextStyle(fontWeight: FontWeight.bold),)),
])),
A simple approach would be to use Spacer() like:
Scaffold(
drawer: Drawer(
child: Column(
children: <Widget>[
Text('Top'),
Spacer(), // use this
Text('Bottom'),
],
),
)
)
here is my solution of a vertical Row with icons in the end of the drawer.
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(
children: <Widget>[
DrawerHeader(
padding: const EdgeInsets.all(7),
decoration: BoxDecoration(
color: AppColors.menuHeaderColor,
),
child: buildHeader(),
),
AccountDrawerRow(),
ListTile(
leading: Icon(Icons.directions_car),
title: Text(translations.button.vehicles),
),
ListTile(
leading: Icon(Icons.calendar_today),
title: Text(translations.button.appointments,),
),
],
),
),
Container(
child: Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
padding: EdgeInsets.all(15.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
InkWell(
onTap: () => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SettingsPage())),
child: Icon(Icons.settings)),
Icon(Icons.help),
Icon(Icons.info),
],
),
),
),
),
],
),
);
}
I'd put it in a row and align all the stuff to bottom using crossAxisAlignment: CrossAxisAlignment.baseline
Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.baseline,
children: <Widget>[
Text(
'12.00',
style: Theme.of(context).textTheme.headline2,
textAlign: TextAlign.start,
),
Text(
'USD',
style: Theme.of(context).textTheme.bodyText2,
textAlign: TextAlign.start,
),
]),
Using Expanded widget to align widget to bottom of column parent widget
Column(
children: [
..other children
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Text(
'Button',
style: TextStyle(
decoration: TextDecoration.underline,
fontSize: 18,
color: Colors.black),
),
),
),
],
),