In my Flutter project, in one page I have some rows including card align vertically. Now, I want this screen to make scroll-able.
I have tried replacing the column to Listview but it didn't work. I also tried to wrap it with SingleChildScrollview but didn't work. It shows like below image-
Here's the code -
HomeFragment.dart
class HomeFragment extends StatefulWidget {
#override
_HomeFragmentState createState() => new _HomeFragmentState();
}
String jwt;
class _HomeFragmentState extends State<HomeFragment> {
List<LastEngagement> _lastEngagements = List<LastEngagement>();
#override
void initState() {
super.initState();
_getLastEngagement;
_getLastEngagement2();
}
void _getLastEngagement() {
Webservice().load(LastEngagement.allLastEngagement).then((newsArticles) => {
setState(() => {
_lastEngagements = newsArticles
})
});
}
void _getLastEngagement2() {
Webservice().load(LastEngagement.allLastEngagement).then((newsArticles) => {
setState(() => {
_lastEngagements = newsArticles
})
});
}
Card showCard(int index) {
return new Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
"https://randomuser.me/api/portraits/men/1.jpg"
),
),
SizedBox(
width: 10.0,
),
Expanded(child: Text(_lastEngagements[index].title)),
],
),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('News'),
),
body:Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: Container(
color: Colors.blue,
child: SizedBox(
height: 100.0,
child: new ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: _lastEngagements.length,
itemBuilder: (BuildContext ctxt, int index) {
return Container(
width: 200.0,
child: showCard(index),
);
},
),
),
),
),
],
mainAxisAlignment: MainAxisAlignment.spaceBetween,
),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
],
),
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Card(
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print('Card tapped.');
},
child: Container(
height: 100,
child: Text('A card that can be tapped'),
),
),
),
),
),
],
)
],
)
);
}
}
Replacing the Column by Listview causes following error-
So, I need a permanent solution to make my screen scroll-able, doesn't matter whatever widgets I use.
You can use SingleChildScrollView or change the column widget to ListView
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('News'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
],
),
));
}
Or
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('News'),
),
body: ListView(
children: <Widget>[],
));
}
Well the previous answers do contain the solution .. at least that's what I think .. but they are buggy answers and that's why it's not working .. try this
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("News"),
),
body: Column(
children: <Widget>[
Expanded(
child: SingleChildScrollView(),
)
],
),
);
}
The expanded gives SingleChildScrollView() full height of the screen allowing it to work :)
I think it should work . Good luck
SingleChildScrollView(
scrollDirection: Axis.vertical,)
Try this instead.
Try below code:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('News'),
),
body: Column(
children: <Widget>[
Expanded
(
child: SingleChildScrollView()
),
flex: 1,
]
)
);
}
Related
I have noticed one issue while applying low shade colors to scaffold,
I have a Column that contains few widgets and expanded Listview,
while scrolling the listview upside, it is shown behind the top widgets of column
I have attached an image,
is there any solution to stop this behaviour of listview
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
backgroundColor: Colors.blue.shade50,
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: 100,
color: Colors.green,
child: Center(child: Text('Balance Card'),),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: 100,
color: Colors.red,
child: Center(child: Text('History Card'),),
),
),
Expanded(
child: ListView.builder(
itemCount: 100,
itemBuilder: (context,index){
return ListTile(
tileColor: Colors.white,
title: Text(index.toString()),
);
}),
),
],
),
),
);
}
Image:
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
return SafeArea(
child: Scaffold(
body: Column(
children: [
Container(
color: Colors.blue.shade50,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: 100,
color: Colors.green,
child: const Center(
child: Text('Balance Card'),
),
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: 100,
color: Colors.red,
child: const Center(
child: Text('History Card'),
),
),
),
],
),
),
Expanded(
child: ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
tileColor: Colors.white,
title: Text(index.toString()),
);
}),
),
],
),
),
);}
I guess you want a look like this.Can you check?
first of all i'm new to flutter and so i am quite confused how to change the "whole" background color in drawer flutter.
i managed to change my ListTile and my so called DrawerHeader to the color i want but the rest (below the ListTile is all white). And there is a line below the DrawerHeader that i don't really want but i can't get rid of it.
here is the code
import 'package:flutter/material.dart';
import '../style/theme.dart' as style;
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
// width: MediaQuery.of(context).,
child: Drawer(
elevation: 0,
child: ListView(
children: <Widget>[
Container(
height: 170,
width: 170,
padding: EdgeInsets.only(top:30),
color: style.Colors.secondColor,
child: Column(children: <Widget>[
Material(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(padding: EdgeInsets.all(20.0),
child: Image.asset('images/circle.png',width: 80, height: 80,),),
//TODO ganti logo
),
],),
),
Container(
color: style.Colors.secondColor,
child: Column(
children: <Widget>[
ListTile(
leading: Icon(Icons.help_outline_sharp),
title: Text('Help', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
ListTile(
leading: Icon(Icons.person),
title: Text('About us', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
],
),
),
],
),
),
);
}
}
here is the photo of the current situation
Here is the photo
Another Question
what if i want to put a single ListTile on the bottom? (like log out)
For changing the background color of drawer you can just swap the Drawer Widget with Container and give color to container
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
elevation: 0,
child: Container(
color: Colors.blue,
child: ListView(
children: <Widget>[
Container(
height: 170,
width: 170,
padding: EdgeInsets.only(top:30),
color: Colors.red,
child: Column(children: <Widget>[
Material(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(padding: EdgeInsets.all(20.0),
child: Image.asset('images/circle.png',width: 80, height: 80,),),
),
],),
),
Container(
color: Colors.red,
child: Column(
children: <Widget>[
ListTile(
leading: Icon(Icons.help_outline_sharp),
title: Text('Help', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
ListTile(
leading: Icon(Icons.person),
title: Text('About us', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
],
),
),
],
),
),
);
}
}
This can be the final code you can use, it has answer to all your three questions
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(
children: <Widget>[
Container(
height: 170,
width: 170,
padding: EdgeInsets.only(top:30),
color: Colors.blue,
child: Column(children: <Widget>[
Material(
borderRadius: BorderRadius.all(Radius.circular(100)),
child: Padding(padding: EdgeInsets.all(20.0),
child: Image.asset('images/circle.png',width: 80, height: 80,),),
),
],
),
),
ListTile(
leading: Icon(Icons.help_outline_sharp),
title: Text('Help', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
ListTile(
leading: Icon(Icons.person),
title: Text('About us', style: TextStyle(fontSize: 18,),),
onTap: () {},
),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: ListTile(
leading: Icon(Icons.logout),
title: Text('Logout')
),
),
],
),
);
}
}
To change the color, wrap the Drawer widget in a Theme widget as follows:
Scaffold(
drawer:Theme(
data:Theme.of(context).copyWith(
canvasColor://the desired color will go here
),
child:Drawer(/*drawer content*/)
)
)
Hope this is useful for someone
I wanted to make a view with two big buttons. I saw an example with Row and Expanded inside, however, Column did not work the same way. I tried with Container of height MediaQuery.of(context).size.height * 0.5, but the paddings I had made the buttons to overflow.
Something like this
EDIT: Complete code
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: Padding(
padding: EdgeInsets.all(12),
child: Column(children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.all(12),
child: OutlineButton(
onPressed: () => null,
child: Text('Button A'),
))),
Expanded(
child: Padding(
padding: EdgeInsets.all(12),
child: OutlineButton(
onPressed: () => null,
child: Text('Button B'),
),
),
)
])));
}
}
You need to add the property crossAxisAlignment: CrossAxisAlignment.stretch in the Column widget to make all the children be stretched in the cross direction (axis X).
You can see a live example of this working here: https://dartpad.dev/825104f44446432166803c0473ea4437
Wrap your Column in Flexible and add in your Column crossAxisAlignment: CrossAxisAlignment.stretch
Flexible(
child: Padding(
padding: EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.all(12),
child: OutlineButton(
onPressed: () => null,
child: Text('Button A'),
))),
Expanded(
child: Padding(
padding: EdgeInsets.all(12),
child: OutlineButton(
onPressed: () => null,
child: Text('Button B'),
),
),
)
])),
)
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
child: Text("1"),
onPressed: (){},
color: Colors.orange,
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
child: Text("2"),
onPressed: (){},
color: Colors.blue,
),
),
)
],
),
)
);
Apparently i tried to make a bottom button for checkout and it seems to be affecting how the body of the app is working. This only happened after i added the bottomnavbar padding etc
heres the link for the snip: https://imgur.com/a/sDhqasr
class _State extends State<CartOverviewScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your Cart'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
Center(child: Text('HI!'),)
],
),
),
bottomNavigationBar: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Card(
margin: EdgeInsets.all(15),
child: Padding(
padding: EdgeInsets.all(8),
child: Row(
children: <Widget>[
Text(
'Total',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(width: 10,),
Chip(label: Text('\$0.00'),)
],
),
),
),
ButtonTheme(
minWidth: double.infinity,
child: RaisedButton(
elevation: 8,
onPressed: () {},
color: colorCustom,
textColor: Colors.white,
child: Text('Checkout'),
),
),
],
),
),
);
}
}
you can also try this
class _State extends State<stat> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Your Cart'),
),
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: Text("Hi"),
),
)
],
),
bottomNavigationBar: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Card(
margin: EdgeInsets.all(15),
child: Padding(
padding: EdgeInsets.all(8),
child: Row(
children: <Widget>[
Text(
'Total',
style: TextStyle(
fontSize: 20,
),
),
SizedBox(
width: 10,
),
Chip(
label: Text('\$0.00'),
)
],
),
),
),
ButtonTheme(
minWidth: double.infinity,
child: RaisedButton(
elevation: 8,
onPressed: () {},
color: Colors.red,
textColor: Colors.white,
child: Text('Checkout'),
),
),
],
),
),
);
}
}
Ahh i found my own answer actually, the problem was caused by bottomNavigationBar hogging the entire body of the app. i just needed to place the following code from below onto the bottomNavigationBar Column.
mainAxisSize: MainAxisSize.min
I have a drawer in my Flutter app, but the default drawer has a very small drag area to show it. How can I increase it?
#override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
return Scaffold(
drawerDragStartBehavior: DragStartBehavior.down,
drawer: Drawer(
child: Column(
children: <Widget>[
UserAccountsDrawerHeader(
accountName: Text(
fullName ?? "",
style: TextStyle(
color: Colors.white,
letterSpacing: 1.0,
fontSize: 16.0,
),
),
You can simply use the drawerEdgeDragWidth property of the Scaffold:
return Scaffold(
appBar: MyAppBar(),
drawer: MyDrawer(),
// Put the width you want here
// In this case the drag area fills the whole screen
drawerEdgeDragWidth: MediaQuery.of(context).size.width,
body: MyBody(),
);
drawer: SizedBox(
width: MediaQuery.of(context).size.width/1.2,
child: Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 10,
),
ListTile(
dense: true,
title: Text(
"Apply for Leave",
style: drawerFont,
),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ApplyLeave()));
},
),
ListTile(
dense: true,
title: Text(
"Approval for Bills",
style: drawerFont,
),
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ApplyBill()));
},
)
],
),
Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Container(
color: Colors.grey[200],
width: double.infinity,
height: 60,
child: Padding(
padding: const EdgeInsets.only(
left: 28.0, top: 15, bottom: 15),
child: GestureDetector(
onTap: () {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ContactUs()));
},
child: Text(
"Contact Us",
style: drawerFont,
),
),
),
),
],
)
],
),
),
),