DrawerLayout: How to make this Custom Layout in flutter - flutter

I have a drawer in which I want to achieve layout posted in the below screenshot.
AllTasks, Today, Complete and Incomplete with numbers are fixed. The user cannot add these. Already added by me. CreateList and Settings as well.
MyList which is added by the user and he can add more like Food, Sports, Reading etc.
Divider as well, maybe after 1 row or 3 rows to show as groups.
Should I use ListView?. Any suggestion, please.

You have a couple of methods to do that the first one using ListView like that:
drawer: new Drawer(
child: new Column(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: const Text('Test Widget'),
accountEmail: const Text('test.widget#example.com'),
margin: EdgeInsets.zero,
onDetailsPressed: () {},
),
new Expanded(
child: new ListView(
padding: const EdgeInsets.only(top: 8.0),
children: <Widget>[
new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: _drawerContents.map((String id) {
return new ListTile(
leading: new CircleAvatar(child: new Text(id)),
title: new Text('Drawer item $id'),
);
}).toList(),
),
// The drawer's "details" view.
new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
new ListTile(
leading: const Icon(Icons.add),
title: const Text('Add account'),
),
new ListTile(
leading: const Icon(Icons.settings),
title: const Text('Manage accounts'),
),
],
),
],
),
),
],
),
)
But it is efficient only with a limited number of list item because all the item of that ListView are rendered at once.
The other way to do that is using a ListView.builder like that:
drawer: new Drawer(
child: new Column(
children: <Widget>[
new UserAccountsDrawerHeader(
accountName: const Text('Test Test'),
accountEmail: const Text('test#example.com'),
margin: EdgeInsets.zero,
onDetailsPressed: () {},
),
new Expanded(
child: new ListView.builder(
itemBuilder: (BuildContext context, int index) =>
new EntryItem(data[index]),
itemCount: data.length,
),
),
],
),
),
In that way your list elements will be rendered one by one during scrolling. You should create one model for both your hardcoded elements and your variable elements and then create a different ListTile (in the example EntryItem).
Let me know if you need more details.
PS. EntryItem example below:
class EntryItem extends StatelessWidget {
const EntryItem(this.entry);
final Entry entry;
Widget _buildTiles(Entry root) {
if(root.counter != null) {
return new ListTile(
leading: Icon(root.icon),
title: Text(root.title),
trailing: new Text(root.counter)
);
} else {
return new ListTile(
leading: Icon(root.icon),
title: Text(root.title),
);
}
}
#override
Widget build(BuildContext context) {
return _buildTiles(entry);
}
}

Related

Add a main drawer to a button in flutter

I am new to flutter and I need to add the main drawer of the app to a button as you can see in the below picture(This is the upper section of the UI of the app)
Any ideas of having the main drawer apply to a button instead of having it normally assign it to the app bar. (This mobile app doesn't have an app bar)
#override
Widget build(BuildContext context) {
var mediaQuery = MediaQuery.of(context);
return Scaffold(
key: scaffoldKey,
body: Stack(
children: <Widget>[
_buildWidgetAlbumCover(mediaQuery),
getMainContentWidget(mediaQuery),
_buildWidgetMenu(mediaQuery),
_buildWidgetFloatingActionButton(mediaQuery),
Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
},
),
],
),
),
],
),
);
}
Widget _buildWidgetMenu(MediaQueryData mediaQuery) {
return Padding(
padding: EdgeInsets.only(
left: 2.0,
top: mediaQuery.padding.top + 2.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
size: 25,
),
padding: EdgeInsets.all(2.0),
// onPressed: () => scaffoldKey.currentState.openDrawer(),
),
],
),
);
}
enter image description here
This is output which I get after having this code. This drawer can't even change or as it is fixed one. I want the normal drawer which is also attached to the _buildWidgetMenu instead of the app bar drawer.
If youre using a sacffold it has a drawer property that you can make use of eg cookbook
return Scaffold(
appBar: AppBar(title: Text(title)),
body: Center(child: Text('My Page!')),
drawer: Drawer(...
opening your drawer from button clicks
var scaffoldKey = GlobalKey<ScaffoldState>();
//required key
Scaffold(
key: scaffoldKey,
drawer: new Drawer(
child: new ListView(
padding: EdgeInsets.zero,...
body:Center(..
IconButton(
icon: Icon(Icons.menu),
//open drawer
onPressed: () => scaffoldKey.currentState.openDrawer(),
),

Fixed buttons between AppBar and SingleChildScrollView (Flutter)

I would like to include buttons between AppBar and ListView. In the example below, the buttons scroll along with the text. I tried to include the SingleChildScrollView within a Column, but was unsuccessful.
I read that the Column widget does not support scrolling. I already searched a lot, but I didn't find an example similar to what I need.
Can someone help me?
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('A Idade do Lobo'),
elevation: 0.0,
backgroundColor: COLOR_MAIN,
),
body: NotificationListener(
onNotification: (notif) {
if (_hasScroll) {
if (notif is ScrollEndNotification && scrollOn) {
Timer(Duration(seconds: 1), () {
_scroll();
setState(() {
_controlButton();
});
});
}
}
return true;
},
child: SingleChildScrollView(
controller: _scrollController,
child: new Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new Center(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new RaisedButton(
onPressed: _showScrollPickerDialog,
child: Text('Rolagem ${_scrollSpeed}'),
),
new RaisedButton(
onPressed: _showTomPickerDialog,
child: Text('TOM ${_tom}'),
),
],
),
),
new Flexible(
fit: FlexFit.loose,
child: new ListView.builder(
shrinkWrap: true,
itemCount: _songDetails.length,
itemBuilder: (context, index) {
return new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: new EdgeInsets.all(5.0),
child: new RichText(
text: TextSpan(children: [
new TextSpan(
text: '${_songDetails[index].line}',
style: _getStyle(
_songDetails[index].type,
),
),
]),
),
),
],
);
},
),
),
],
),
),
),
floatingActionButton: _controlButton(),
);
}
}
You can use bottom properly of AppBar to achieve desire UI.
Following example clear your idea.
import 'package:flutter/material.dart';
class DeleteWidget extends StatefulWidget {
const DeleteWidget({Key key}) : super(key: key);
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("your title"),
bottom: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, 40),
child: Center(
child: new Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new RaisedButton(
onPressed: () {},
child: Text('Rolagem '),
),
new RaisedButton(
onPressed: () {},
child: Text('TOM '),
),
],
),
),
),
),
body: Container(
child: ListView.builder(
itemBuilder: (context, int index) {
return Text(index.toString());
},
itemCount: 100,
),
));
}
}

Listview not showing inside a Row in Flutter

I am trying to show a listview after some texts in a column. The text shows properly inside the first Row until I add a listview inside the next row. Everything disappears after adding the ListView.
Here is the Code:
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Row(
children: <Widget>[
Text(
"Prayer Time",
style: TextStyle(fontSize: 20, fontWeight:
FontWeight.normal),
),
],
),
Row(
children: <Widget>[myList()],
),
],
),
),
floatingActionButton: FloatingActionButton(
tooltip: 'Add Alarm',
child: Icon(Icons.add),
backgroundColor: const Color(0xff0A74C5),
),
);
}
Expanded myList() {
return Expanded(
child: ListView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(androidVersionNames[position]),
);
},
itemCount: androidVersionNames.length,
)
);
}
}
change like this:
Expanded(
child: Row(
children: <Widget>[myList()],
),
),
Your ListView should have a fixed Size. Try to wrap the ListView inside a Container.
I run your code and fixed it. Replace your myList() with this code bellow:
Expanded myList() {
return Expanded(
child: Container(
width: double.infinity,
height: 200,
child: ListView.builder(
itemBuilder: (context, position) {
return Card(
child: Text(androidVersionNames[position]),
);
},
itemCount: androidVersionNames.length,
),
)
);
}

Loop Cards Flutter

I have been researching Flutter and a question arose --
I have an array with some information, and I need to add cards based on this array.
Currently, I create a loop and add the cards which follow the structure of my array and my program listed below. Note that when I call statement passing the parameters, the code runs without any problem, but the following code does not work for me:
import "package:acessorias/pages/global.variables.dart";
import "package:flutter/material.dart";
class Comunicados extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Center(
child: SizedBox(
width: 150,
child: Image.asset("assets/image/logo.png"),
),
),
actions: <Widget>[
Container(
width: 60,
child: FlatButton(
child: Icon(
Icons.search,
color: Color(0xFFBABABA),
),
onPressed: () => {},
),
),
],
),
body: Container(
color: Color(0xFFF2F3F6),
child: ListView(
children: <Widget>[
comunicado(comunicados[0]["LogNome"], comunicados[0]["EmComDTH"],
comunicados[0]["EmComDesc"]),
comunicado(comunicados[1]["LogNome"], comunicados[1]["EmComDTH"],
comunicados[1]["EmComDesc"]),
comunicado(comunicados[2]["LogNome"], comunicados[2]["EmComDTH"],
comunicados[2]["EmComDesc"]),
comunicado(comunicados[3]["LogNome"], comunicados[3]["EmComDTH"],
comunicados[3]["EmComDesc"]),
comunicado(comunicados[4]["LogNome"], comunicados[4]["EmComDTH"],
comunicados[4]["EmComDesc"]),
comunicado(comunicados[5]["LogNome"], comunicados[5]["EmComDTH"],
comunicados[5]["EmComDesc"])
],
),
),
);
}
}
Widget comunicado(user, data, msg) {
return Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage("assets/image/foto.png"),
),
title: new Text(user),
subtitle: Text(data),
trailing: Icon(Icons.more_vert),
),
/*Container(
child: Image.asset("assets/image/post.png"),
),*/
Container(
padding: EdgeInsets.all(10),
child: Text(msg),
),
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: Icon(Icons.favorite),
onPressed: () {},
),
FlatButton(
child: Icon(Icons.share),
onPressed: () {},
),
],
),
),
],
),
);
}
Solution
body: ListView.builder(
itemCount: comunicados.length,
itemBuilder: (context, index) {
/*return ListTile(
title: Text('${comunicados[index]}'),
);*/
return comunicado(comunicados[index]['LogNome'],
comunicados[index]["EmComDTH"], comunicados[index]["EmComDesc"]);
},
),
You can use data model in another dart file like Comunicado.dart
class Comunicado{
String user;
String data;
String msg;
Comunicado(
{this.user, this.data, this.msg});
}
after that you can make list of data model with the static data or etc like
List getComunicado(){
return[
Comunicado(
user: comunicados[0]["LogNome"],
data: comunicados[0]["EmComDTH"],
msg: comunicados[0]["EmComDesc"],
),
Comunicado(
user: comunicados[1]["LogNome"],
data: comunicados[1]["EmComDTH"],
msg: comunicados[1]["EmComDesc"],
),
]
}
in my case, i put it into initial state and don't forget to declare comm
#override
void initState() {
super.initState();
comm= getComunicado();
}
for custom card
Card makeCard(Comunicado newComm) => Card(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
ListTile(
leading: CircleAvatar(
backgroundImage: AssetImage("assets/image/foto.png"),
),
title: new Text("${newComm.user}"),
subtitle: Text("${newComm.data}"),
trailing: Icon(Icons.more_vert),
),
/*Container(
child: Image.asset("assets/image/post.png"),
),*/
Container(
padding: EdgeInsets.all(10),
child: Text("${newComm.msg}"),
),
ButtonTheme.bar(
child: ButtonBar(
children: <Widget>[
FlatButton(
child: Icon(Icons.favorite),
onPressed: () {},
),
FlatButton(
child: Icon(Icons.share),
onPressed: () {},
),
],
),
),
],
),
);
and for last you can call make card on listview
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: comm.length,
itemBuilder: (BuildContext context, int index) {
return makeCard(comm[index]);
},
),

How can I make the child of my Drawer a Column?

I created a Drawer with a child of a ListView like the core documentation suggests. It works. But I want to put a widget fixed at the bottom of my drawer. So I wrapped my ListView in a Column. But when I do this my Drawer contents disappear completely.
final Widget _leftDrawer = Drawer(
child: Column(
children: <Widget>[
ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Image.asset('assets/images/logo_1024.png'),
),
ListTile(
title: Text('Line 1'),
),
ListTile(
title: Text('Line 2'),
),
AboutListTile(),
],
),
],
),
);
When you put a ListView inside a Column, the ListView does not know about its boundary anymore. You need to wrap your ListView inside an Expanded widget.
final Widget _leftDrawer = Drawer(
child: Column(
children: <Widget>[
Expanded(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Image.asset('assets/images/logo_1024.png'),
),
ListTile(
title: Text('Line 1'),
),
ListTile(
title: Text('Line 2'),
),
AboutListTile(),
],
),
),
],
),
);