I want to add a button, below the listview to navigate to the next page! But I am unsure of the layout.
#override
Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(
title:const Text("Welcome"),
centerTitle: true,
),
body:Center(
child:SizedBox(
child:ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
color: Colors.amber[colorCodes[index]],
child: Center(child: Text('Entry ${entries[index]}')),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
child: TextButton(onPressed: onPressed, child: child) // Where am i suppose to add this?
)
)
);
I am unsure of the layout! Any help will be greatly appreciated!
Simply wrap the ListView with a Column:
#override
Widget build(BuildContext context)
{
return Scaffold(
appBar: AppBar(
title:const Text("Welcome"),
centerTitle: true,
),
body:Column(
children: [
Center(
child:SizedBox(
child:ListView.separated(
padding: const EdgeInsets.all(8),
itemCount: entries.length,
itemBuilder: (BuildContext context, int index) {
return Container(
height: 50,
color: Colors.amber[colorCodes[index]],
child: Center(child: Text('Entry ${entries[index]}')),
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
child: TextButton(onPressed: onPressed, child: child) // Where am i suppose to add this?
)
),
],
);
After you done this, you can add as many widgets as you want.
Hope it helps!
Related
I'd like to add some empty tiles to the bottom of my listview so that I can put "See More" button on that part. The data I'm displaying on the screen is from Firebase. This is something I learned from YouTube tutorials. This is my code.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: StreamBuilder(
stream: Collection.limit(10).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
return !snapshot.hasData
? Center(child: CircularProgressIndicator())
: ListView(
children: snapshot.data!.docs.map((document) {
return Center(
child: Card(
margin: EdgeInsets.fromLTRB(5.0, 0.0, 5.0, 1.0),
child: ListTile(
title: Text(document['title']),
subtitle: Text(document['body']),
onTap: () async { },
),
),
);
}).toList(),
);
},
),
);
}
Some people have already advised me to use ListView.builder, but I'm not sure how to implement it in my code. I repeatedly tried to use ListView.Builder but failed.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: StreamBuilder(
stream: Collection.limit(10).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (_, index) => Center(
child: Column(
children: [
Card(
margin: EdgeInsets.fromLTRB(5.0, 0.0, 5.0, 1.0),
child: ListTile(
title: Text("some text"),
subtitle: Text("some text"),
onTap: () async {},
),
),
TextButton(onPressed: () {}, child: Text("See More"))
],
)));
},
),
);
}
I am trying to navigate to a route and this exception happen. Have look at my code and I don't think I have a FAB and Hero inside this route. Is it because when you tap on each List item, it will show a dialog with Gridview on it? Someone care to explain to me how can this exception happened? It doesn't produce any error on user thought, just throw an exception.
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Daftar Dokter")),
body: ListView.separated(
separatorBuilder: (BuildContext context, int i) => Divider(color: Colors.grey[400]),
itemCount: widget.data.length,
itemBuilder: (context, index) {
Doctor doctor = widget.data[index];
return InkWell(
onTap: (){
_buildDialog(context, scheduleService, doctor.doctorId);
},
child: Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 50,
height: 50,
child: Placeholder(),
),
),
Flexible(
child: SizedBox(
child: ListTile(
title: Text(doctor.name),
subtitle: Text(doctor.specializationName),
),
)
)
],
),
);
}
)
);
}
}
Hope it will solve your issue:
onItem Builder:
itemBuilder: (context, index) {
return Hero(
tag: "itemTag $index",
child: Material(
child: InkWell(
onTap: () {
// _buildDialog(context, scheduleService, doctor.doctorId);
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => Wisgets(
tag: "itemTag $index",
)));
},
child: Row(
children: <Widget>[
Text("Item $index"),
],
),
),
),
);
},
Child Widget for row
class Wisgets extends StatelessWidget {
final String tag;
const Wisgets({Key? key, required this.tag}) : super(key: key);
#override
Widget build(BuildContext context) {
return Hero(
tag: tag,
child: Scaffold(
appBar: AppBar(
title: Text("Child"),
),
body: Column(
children: [
Text("got $tag"),
],
),
),
);
}
}
I am trying to create a custom drawer.
I want to make DrawerHeader fixed. However, I want ExpansionTile and ListView scrollable.
https://imgur.com/a/lWeDWOO ,
https://imgur.com/a/tR68ECK
class _NavigationDrawerState extends State<NavigationDrawer> {
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
DrawerHeader(
child: Column(....),
ExpansionTile(
title: Text('Roles'),
children: [
ListView.builder(
itemBuilder: _buildRolesList,
itemCount: roles.length,
shrinkWrap: true,
)
],
),
ListView.builder(
shrinkWrap: true,
itemBuilder: _buildList,
itemCount: myList.length,
),
],
),
);
}
Widget _buildList(BuildContext context, int index) {
return ListTile(
leading: Icon(icons[myList[index].toLowerCase()]),
title: Text(myList[index]),
);
}
Widget _buildRolesList(BuildContext context, int index) {
return ListTile(
dense: true,
title: Text(roles[index]),
onTap: () {},
);
}
}
Try this:
class _NavigationDrawerState extends State<NavigationDrawer> {
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
children: <Widget>[
ExpansionTile(
title: Text('Roles'),
children: [
SizedBox(
height: MediaQuery.of(context).size.height - 100,
child: ListView.builder(
itemBuilder: _buildRolesList,
itemCount: roles.length,
shrinkWrap: true,
),
)
],
),
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: _buildList,
itemCount: myList.length,
),
),
],
),
);
}
Widget _buildList(BuildContext context, int index) {
return ListTile(
leading: Icon(icons[myList[index].toLowerCase()]),
title: Text(myList[index]),
);
}
Widget _buildRolesList(BuildContext context, int index) {
return ListTile(
dense: true,
title: Text(roles[index]),
onTap: () {},
);
}
I'm trying to make a dynamic menu (via a json file). When I put my code in the body it's working fine. But when I put it in my Drawer, the drawer is blank, even my DrawerHeader disappear.
My code:
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My App'),
backgroundColor: Colors.green,
),
body: ListView.builder( // <---------- WORKING
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(data[i]["title"]),
);
}),
drawer: Drawer(
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
Container(
height: 85.0,
child: DrawerHeader(
child: Text(
'Categories',
style: new TextStyle(fontSize: 18.0, color: Colors.white),
),
decoration: BoxDecoration(
color: Colors.green,
),
),
),
ListView.builder( // <---------- NOT WORKING
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(data[i]["title"]),
);
})
],
),
),
);
}
full code
Your ListView.builder widget needs to be inside a widget with a fixed height.
You can set it inside a Container:
Container(
height: double.maxFinite,
child: ListView.builder(
itemCount: data == null ? 0 : data.length,
itemBuilder: (BuildContext context, i) {
return new ListTile(
title: new Text(data[i]["title"]),
);
}))
What is the preferred way to achieve a nested ListView, or in other words, ListView Widgets that could be included within a scrollable parent?
Imagine a "Reports" page, where a section is an itemized list.
For child ListView, use that parameter:
shrinkWrap: true,
physics: ClampingScrollPhysics(),
Adding physics: ClampingScrollPhysics() and shrinkWrap: true did the trick for me.
sample code:
#override
Widget build(BuildContext context) {
return Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: 123,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Parent'),
ListView.builder(
itemCount: 2,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Text('Child');
}),
],
);
}),
)
],
),
);
}
If you want to have the inner ListView be scrollable independently of the main scroll view, you should use NestedScrollView. Otherwise, use a CustomScrollView.
Here is some code illustrating the NestedScrollView approach.
import 'package:flutter/material.dart';
void main() {
runApp(new MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
new SliverAppBar(
pinned: true,
title: new Text('Flutter Demo'),
),
];
},
body: new Column(
children: <Widget>[
new FlutterLogo(size: 100.0, colors: Colors.purple),
new Container(
height: 300.0,
child: new ListView.builder(
itemCount: 60,
itemBuilder: (BuildContext context, int index) {
return new Text('Item $index');
},
),
),
new FlutterLogo(size: 100.0, colors: Colors.orange),
],
),
),
);
}
}
For inner Listview I have just added below code and it solved for me
shrinkWrap: true,
physics: ScrollPhysics(),
Screenshot:
Code:
var _container = Container(
height: 200,
color: Colors.blue,
margin: EdgeInsets.symmetric(vertical: 10),
);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("ListView")),
body: Padding(
padding: const EdgeInsets.all(40.0),
child: ListView( // parent ListView
children: <Widget>[
_container,
_container,
Container(
height: 200, // give it a fixed height constraint
color: Colors.teal,
// child ListView
child: ListView.builder(itemBuilder: (_, i) => ListTile(title: Text("Item ${i}"))),
),
_container,
_container,
_container,
],
),
),
);
}
Thanks to Serdar Polat:
ListView.builder( // outer ListView
itemCount: 4,
itemBuilder: (_, index) {
return Column(
children: [
Container(
color: Colors.blue,
alignment: Alignment.center,
child: Text('Header $index'),
),
ListView.builder( // inner ListView
shrinkWrap: true, // 1st add
physics: ClampingScrollPhysics(), // 2nd add
itemCount: 10,
itemBuilder: (_, index) => ListTile(title: Text('Item $index')),
)
],
);
},
)
shrinkWrap to wrap your content and ClampingScrollPhysics to use the parent scroll
ListView.builder(
shrinkWrap: true,
physics: const ClampingScrollPhysics(),
itemCount: yourList.length,
itemBuilder: (context, index) => YourWidget(items[index]),
),
I use this:
scrollController.addListener(onScroll);
void onScroll(){
if(scrollController.offset == 0.0
|| scrollController.position.extentBefore == 0.0
|| scrollController.position.extentAfter == 0.0){
scrollPhysics = NeverScrollableScrollPhysics();
Future.delayed(Duration(seconds: 1), (){
scrollPhysics = ClampingScrollPhysics();
setState((){});
});
setState((){});;
}
}
Expanded(
child: ListView.builder(
shrinkWrap: true,
padding: const EdgeInsets.all(8),
itemCount: requestList.length,
itemBuilder: (BuildContext context, int index) {
int que = index;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.only(
left: 20,
top: 10,
bottom: 10,
right: 20),
child: Text(
'${que++} . ${requestList[index].question}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
color: HexColor(HexColor.black),
fontFamily: 'montserrat_regular',
decoration: TextDecoration.none,
),
)),
ListView.builder(
itemCount: requestList[index].questionOptions!.length,
physics: ClampingScrollPhysics(),
shrinkWrap: true,
itemBuilder: (BuildContext context, int subindex) {
return Row(
children: <Widget>[
Radio(
value: 1,
groupValue: radio_value[index],
onChanged: (values) async {
setState(() {
radio_value[index] = 1;
qutionCheckModel[index].response =
"yes";
});
}),
Container(
child: Text(
requestList[index].questionOptions![subindex],
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
color: HexColor(HexColor.black),
fontFamily: 'montserrat_regular',
decoration: TextDecoration.none,
),
),
),
],
);
}),
],
);
}),
),