Flutter Drawer: Is it possible to scroll only part of the drawer? - android

I'm trying to build an app where you could open a drawer and scroll only content below DrawerHeader(). When I have DrawerHeader as a child of ListView, naturally it scrolls with the whole list. I've tried
Drawer(child:Column(children: <Widget>[DrawerHeader(), ListView()]))
but seems that it crashes the app.
test drawer
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
drawer: Drawer(
child: ListView(
children: <Widget>[
DrawerHeader(
child: Text('Projects related tools'),
decoration: BoxDecoration(color: Colors.blue),
),
ExpansionTile(
title: Text('Project 1'),
children: <Widget>[
Text('Property 1'),
Text('Property 2'),
],
),
],
),
),
body: SafeArea(child: ListView()),
));
}
}

Wrap your ListView with an Expanded:
Drawer(
child: Column(
children: <Widget>[
DrawerHeader(
...
),
Expanded(
child: ListView(
...
),
),
],
),
),

Related

How to have a ListView without scrolling the parent column view in flutter?

Please look at this image Home Page
Now when I scroll the ListView it becomes like this -
Home Page
Now I know the reason why this is happening, it is because I used ListView as a parent to this entire view and added ListView.builder() and other widgets as its child.
What I want is to scroll the ListView.builder() without scrolling the entire page.
For this I first tried to use Column as parent but that ended up giving the overflow pixels error.
And then I set the physics: const NeverScrollableScrollPhysics() inside the parent ListView but after that it made my ListView.builder() to show all of its list items.
Here is my Code for Home Screen
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 45, bottom: 24),
children: [
header(),
const SizedBox(height: 36),
const BalanceCard(),
const SizedBox(height: 36),
Recent()
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: bottomNavigationBar(),
),
],
),
); }
Recent List Code
class RecentItems extends StatefulWidget {
final List<Transaction> transactions;
RecentItems({required this.transactions});
#override
State<RecentItems> createState() => _RecentItemsState();
}
class _RecentItemsState extends State<RecentItems> {
#override
Widget build(BuildContext context) {
return SizedBox(
height: 450,
child: Expanded(child: ListView.builder(
itemBuilder: (context, index) {
final item = widget.transactions[index].toString();
return Dismissible(
direction: DismissDirection.endToStart,
key: UniqueKey(),
onDismissed: (direction) {
setState(() {
widget.transactions.removeAt(index);
});
// Then show a snackbar.
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(content: Text('Transaction Deleted')));
},
background: Container(
color: Colors.red,
alignment: AlignmentDirectional.centerEnd,
child: const Padding(
padding: EdgeInsets.fromLTRB(0.0, 0.0, 15.0, 0.0),
child: Icon(
EvaIcons.trash2,
color: Colors.white,
),
),
),
child: Card(
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: ListTile(
leading: CircleAvatar(
radius: 30,
foregroundImage: widget.transactions[index].Image,
backgroundColor: primaryColor,
),
title: Text(
widget.transactions[index].title,
style: const TextStyle(color: secondaryColor),
),
subtitle: Text(
DateFormat.yMMMd().format(widget.transactions[index].date),
),
trailing: Text(
'\$${widget.transactions[index].amount}',
style: const TextStyle(color: secondaryColor),
),
),
),
);
},
itemCount: widget.transactions.length,
),)
);
}
}
Recent Widget -
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Recent Transactions',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: secondaryColor),
),
const SizedBox(height: 5),
RecentItems(transactions: _userTransactions),
],
),
)
The entire screen scrolls because Recent() is included in the same ListView as header() and balanceCard().
Try something like this:
Scaffold(
body: Column(
children: [
Expanded(
child: ListView(
padding: const EdgeInsets.only(top: 45, bottom: 24),
children: [
header(),
const SizedBox(height: 36),
const BalanceCard(),
const SizedBox(height: 36),
],
),
),
// Recent items removed from ListView
Recent(),
Align(
alignment: Alignment.bottomCenter,
child: bottomNavigationBar(),
),
],
),
)
I hope this helps.
By simplifying your code, this is an example of a layout where you have a single Column in the Scaffold. The Column contains some sized, unsized and aligned children.
One child, Recent is a ListView, without explicit height, but wrapped into an Expanded widget. This way it will occupy all the remaining area left by the other children, and it will be scrollable.
(You will run into trouble with this if the children without Recent occupy all the available area.)
Please have a look at this code, you can copy-paste it into a DartPad fiddle:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => Scaffold(
body: Column(
children: [
const Text('header()'),
const SizedBox(height: 36),
const Text('BalanceCard()'),
const SizedBox(height: 36),
Expanded(child: Recent()),
const Align(
alignment: Alignment.bottomCenter,
child: Text('bottomNavigationBar()'),
),
],
),
);
}
class Recent extends StatelessWidget {
#override
Widget build(BuildContext context) => ListView.builder(
itemCount: 100, itemBuilder: (context, index) => Text('Item $index'));
}

Link with a image and gestureDetector

I am making a app for fun and to learn. When I added interactivity by first time, I found a error by adding gesturedetector. Gesture detector has to open a new function which is a window with more things. The gesture detector is inside a column, inside a container inside a ListView (The order is LsitView->Container->GestureDetector)
class _HomePageUserState extends State<HomePageUser> {
#override
Widget build(BuildContext context) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
//itemCount: 100,
itemBuilder: (context, index) {
return Center(
child: Container (
height: 300,
width: 400,
alignment:Alignment.center,
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.circular(10.0),
),
child: Stack(
children: <Widget> [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(padding: EdgeInsets.all(10), child: Text('Nombre del comercio'),),
Padding(padding: EdgeInsets.only(left: 10), child: Icon(Icons.open_in_new),),
],
),
Expanded(
child: GestureDetector(
child: Image.network('https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Spaghetti_Bolognese_mit_Parmesan_oder_Grana_Padano.jpg/800px-Spaghetti_Bolognese_mit_Parmesan_oder_Grana_Padano.jpg',
fit: BoxFit.fitWidth,
height: 200,),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const VistaUsuario()),
);
},
onLongPress: () {},
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(padding: EdgeInsets.all(10), child: Text('Estrellas'),),
Padding(padding: EdgeInsets.all(10), child: Text('Precio (rango)'),),
],
),
],
),
],
),
),
);
},
);
}
}
The error is:
Se produjo una excepción. FlutterError (Vertical viewport was given unbounded height. Viewports expand in the scrolling direction to fill their container. In this case, a vertical viewport was given an unlimited amount of vertical space in which to expand. This situation typically happens when a scrollable widget is nested inside another scrollable widget. If this widget is always nested in a scrollable widget there is no need to use a viewport because there will always be enough vertical space for the children. In this case, consider using a Column instead. Otherwise, consider using the "shrinkWrap" property (or a ShrinkWrappingViewport) to size the height of the viewport to the sum of the heights of its children.)
Try to wrap your GestureDetector in SingleChildScrollView .this will scroll the page.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test page'),
),
body:SingleChildScrollView(
child:Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
child: Image.network('https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Spaghetti_Bolognese_mit_Parmesan_oder_Grana_Padano.jpg/800px-Spaghetti_Bolognese_mit_Parmesan_oder_Grana_Padano.jpg',
fit: BoxFit.fitWidth,
height: 200,),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => const VistaUsuario()),
);
},
),
],
),
),
),
);
}
Another Solution is to use Expanded widget.This will expand the image to take rest of the page
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test page'),
),
body:Center(
child:Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 0,
),
Expanded(
child: GestureDetector(
child: Image.network('https://upload.wikimedia.org/wikipedia/commons/thumb/2/20/Spaghetti_Bolognese_mit_Parmesan_oder_Grana_Padano.jpg/800px-Spaghetti_Bolognese_mit_Parmesan_oder_Grana_Padano.jpg',
fit: BoxFit.fitWidth,
height: 200,),
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) => const VistaUsuario()),
);
},
),
),
],
),
),
),
);
}

the app is crashing saying stack overflow

i obseved that the app is crashing after i add that listview builder if we dont add that app running smoothly
i am still a new bee so i dont know much i just started
if u want u can see whole app code in
https://github.com/Pradeep7976/E_com_app/tree/master/shop_app
this is a garbage i am writing this cause stack overflow is suggesting to add more description it is saying the post is mostly code add some more description
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/cart.dart' show Cart;
import '../widgets/cart_item.dart';
import '../providers/orders.dart';
class CartScreen extends StatelessWidget {
static const routeName = '/cart';
#override
Widget build(BuildContext context) {
final cart = Provider.of<Cart>(context);
return Scaffold(
appBar: AppBar(
title: Text('Your Cart'),
),
body: Column(
children: <Widget>[
Card(
margin: EdgeInsets.all(5),
child: Padding(
padding: EdgeInsets.all(15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
'Total',
style: TextStyle(fontSize: 20),
),
Spacer(),
Chip(
label: Text(
'₹${cart.totalAmount.toStringAsFixed(2)}',
style: TextStyle(color: Colors.yellow),
),
backgroundColor: Theme.of(context).primaryColor,
),
FlatButton(
child: Text('ORDER NOW'),
onPressed: () {
Provider.of<Orders>(context, listen: false).addOrder(
cart.items.values.toList(),
cart.totalAmount,
);
cart.clear();
},
textColor: Theme.of(context).primaryColor,
),
],
),
),
),
SizedBox(height: 10),
Expanded(
child: ListView.builder(
itemBuilder: (ctx, i) => CartItem(
cart.items.values.toList()[i].id,
cart.items.keys.toList()[i],
cart.items.values.toList()[i].price,
cart.items.values.toList()[i].quantity,
cart.items.values.toList()[i].title,
),
itemCount: cart.items.length,
),
)
],
),
);
}
}
this happens when there is an infinite loop in your app
perhaps your problem is the number of cart items which tries to build so many widgets

Is there a way to put tabs inside a drawer in Flutter?

I currently am new in Flutter and is looking for help for a feature I'm trying to implement. I have too many information in my drawer currently so I am trying to put tabs inside the drawer so people can access different kinds of information inside the drawer. I photoshopped a picture to show the idea that I have in my head. Drawer with Tab Pictures shown here. So far, I've tried the DefaultTabController but couldn't get it to work so if anyone has any other ideas or a different way of approaching it I would be really grateful.
Thanks in advance!
You can copy paste run full code below
You can wrap DefaultTabController with Drawer
code snippet
return Scaffold(
...
drawer: Drawer(
child: DefaultTabController(
length: 3,
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
),
Container(
height: 50,
color: Colors.black12,
child: TabBar(
labelColor: Colors.deepOrange,
unselectedLabelColor: Colors.white,
tabs: [
Tab(text: "First"),
Tab(text: "Second"),
Tab(text: "Third"),
]),
),
Expanded(
child: Container(
color: Colors.green,
child: TabBarView(children: [
Container(
child: Text("First Body"),
),
Container(
child: Text("Second Body"),
),
Container(
child: Text("Third Body"),
),
]),
),
),
],
),
),
),
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
drawer: Drawer(
child: DefaultTabController(
length: 3,
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
),
Container(
height: 50,
color: Colors.black12,
child: TabBar(
labelColor: Colors.deepOrange,
unselectedLabelColor: Colors.white,
tabs: [
Tab(text: "First"),
Tab(text: "Second"),
Tab(text: "Third"),
]),
),
Expanded(
child: Container(
color: Colors.green,
child: TabBarView(children: [
Container(
child: Text("First Body"),
),
Container(
child: Text("Second Body"),
),
Container(
child: Text("Third Body"),
),
]),
),
),
],
),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}

Flutter Expanded widget error even if theres a Flex parent

Hi can you guys help me with this, I know that the Expanded widget requires a Flex parent. but for some reason, mine gives an error:
my code are:
import 'package:flutter/material.dart';
class InputPage extends StatefulWidget {
#override
_InputPageState createState() => _InputPageState();
}
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(child: Text('BMI CALCULATOR')),
),
body: Column(
children: <Widget>[
Expanded(
child: Container(
child: ReusableCard(colour: Color(0xFF141A3C)),
),
),
],
),
);
}
}
class ReusableCard extends StatelessWidget {
//CUSTOM CONSTRUCTOR
//the color from the Stateful Widget from above is passed in to the INPUT of ReusableCard({PASSED IN HERE}),
ReusableCard({this.colour});
Color colour;
#override
Widget build(BuildContext context) {
return Expanded(
child: Container(
margin: EdgeInsets.all(15.0),
// height: 200.0,
// width: 170.0,
decoration: BoxDecoration(
color: colour,
borderRadius: BorderRadius.circular(10.0),
),
),
);
}
}
UPDATE
Ive tried adding another Extended widget AS A CHILD of Column() but the error reappears
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(child: Text('BMI CALCULATOR')),
),
body: Column(
children: <Widget>[
Expanded(
child: Row(
// <------ change this Container to a Row or Column
children: <Widget>[
ReusableCard(colour: Color(0xFF141A3C)),
ReusableCard(colour: Color(0xFF141A3C)),
],
),
),
Expanded(
child: ReusableCard(
colour: Color(0xFF141A3C),
),
)
],
),
);
}
}
Your ReusableCard (which returns an Expanded widget) is wrapped within a Container class. This is what's giving you the error. To fix this, you can simply change your Container class to a Row or Column:
class _InputPageState extends State<InputPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(child: Text('BMI CALCULATOR')),
),
body: Column(
children: <Widget>[
Expanded(
child: Container( // <------ change this Container to a Row or Column
child: ReusableCard(colour: Color(0xFF141A3C)
),
),
),
],
),
);
}
}

Categories

Resources