body: ListView.builder(
// i do not know where should i put the sizedBox to make these image has space to separate
itemCount: a.length,
itemBuilder: (context, index) {
return GestureDetector(
child: ListTile(title: (a[index][0])),
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => a[index][1]));
},
);
},
),
Use the ListView.separated, it has a separatorBuilder property that will help you to add the SizedBox, here the example:
#override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.separated(
itemCount: 10, // add the length of the array of items, for example data.length
itemBuilder: (BuildContext context, int index) => Text('Hola $index'), // here build the cards body
separatorBuilder: (BuildContext context, int index) => const SizedBox(height: 15), // here the SizedBoxed
),
);
}
Related
I have to use showModalBottomSheet for displaying list of menu item. But I am unable to dynamically set the height of the bottomsheet. Please help me to solve this issue. Thankyou.
This is how you can dynamically change the bottomsheet height based on the length of the list in the bottom sheet. But be aware of that you need to use statefulbuilder in the showModalBottomSheet to be able to setState the list.
List<int> myList = [1,2,3,4,5,6];
#override
Widget build(BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('showModalBottomSheet'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, _setState){
return Container(
height: myList.length * 100,
color: Colors.amber,
child: ListView.builder(
itemCount: myList.length,
itemBuilder: (BuildContext ctxt, int index) {
return Row(
children: [
Text(myList[index].toString()),
TextButton(
onPressed: () {
_setState((){
myList = myList.where((value) => value != myList[index]).toList();
});
},
child: Text("delete"),
)
]);
}
)
);
}
);
},
);
},
),
);
}
I'm using ListView.separated() inside in the builder of showModalBottomSheet(). I would like for the BottomSheet to resize based on the number of ListTile widgets displayed.
Here's my code:
showModalBottomSheet(
context: context,
backgroundColor: Colors.blueGrey,
isScrollControlled: false,
builder: (context) => Wrap(
children: [
ListView.separated(
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) =>
ListTile(
title: Text(lists[index].listName),
),
separatorBuilder: (BuildContext context, int index) =>
Divider(),
),
],
),
);
I've tried wrapping the ListView inside a Wrap widget, but I got an error because the child of Wrap doesn't have a set height. Any tips?
You can do this by using the shrinkWrap parameter in the ListView widget.
showModalBottomSheet(
context: context,
builder: (context) => ListView.separated(
shrinkWrap: true,
itemCount: 4,
itemBuilder: (BuildContext context, int index) => ListTile(
title: Text('item $index'),
),
separatorBuilder: (BuildContext context, int index) => Divider(),
),
);
I am trying to add 70.0px at the bottom of each of my Container item in my ListView.
I have been looking at a lot of answers from StackOverflow and trying them in many different ways, and adding padding inside ListView doesn't work somehow. However, I still couldn't tackle it.
Can someone please give me some advice please?
class PortfolioRow extends StatelessWidget {
#override
Widget build(BuildContext context) {
return LayoutBuilder(builder: (context, constraints) {
return Container(
margin: const EdgeInsets.only(bottom: 70.0),
child: StreamBuilder(
stream: Firestore.instance
.collection('portfolio')
.where('category')
.snapshots(),
builder: (context, snapshot) {
return ListView.builder(
physics: ScrollPhysics(),
shrinkWrap: true,
itemExtent: 450.0,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) => portfolioContainer(
context, snapshot.data.documents[index]));
}));
...
}
Widget portfolioContainer(
BuildContext context, DocumentSnapshot documentSnapshot) {
return Align(
child: SizedBox(
height: 540,
width: 330,
child: Container( // if I add padding bottom here, there will be a pixel overflow in my container
child: Column(children: [
Container(
...
}
ListView has a named constructor for exactly that : ListView.separated(). The separatorBuilder parameter lets you specify a widget that will be added at the bottom of each item :
ListView.separated(
itemCount: 25,
separatorBuilder: (BuildContext context, int index) => Divider(),
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('item $index'),
);
},
)
I have data from firestore
I need to display the name in a single page and the name of content in another page and so episodes
Is there a better way than this
tvshow page
FutureBuilder(
future: Provider.of<Data>(context).fetchShows(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
tvSelected = index;
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return SeasonsPage(selectedTv: tvSelected);
}));
},
child: Container(
margin: EdgeInsets.all(10.0),
width: 100.0,
color: Colors.orangeAccent,
child: Text(snapshot.data[index].name),
),
);
},
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
seasons page:
FutureBuilder(
future: Provider.of<Data>(context).fetchShows(),
builder: (context, snapshot) => snapshot.hasData
? ListView.builder(
itemCount: snapshot.data[selectedTv].content.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
selectedSeason = index;
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return EpisodesPage(
selectedTv: selectedTv,
selectedSeason: selectedSeason,
);
}));
},
child: Container(
margin: EdgeInsets.all(10.0),
width: 100.0,
color: Colors.orangeAccent,
child: Text(
snapshot.data[selectedTv].content[index].name),
),
);
},
)
: Center(child: CircularProgressIndicator()),
),
episodes page:
FutureBuilder(
future: Provider.of<Data>(context).fetchShows(),
builder: (context, snapshot) => snapshot.hasData
? ListView.builder(
itemCount: snapshot.data[selectedTv].content[selectedSeason]
.episodes.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.all(10.0),
width: 100.0,
color: Colors.orangeAccent,
child: Text(snapshot.data[selectedTv]
.content[selectedSeason].episodes[index]),
);
},
)
: Center(child: CircularProgressIndicator()),
),
look at when I pass a route page
.............................
.............................
...........................
Firstly you you create a new provider class that will hold the indices of the currently selected tv,episode and season as shown bellow:
class CurrentIndexProvider with ChangeNotifier {
int _selectedTv;
int _selectedSeason;
int _selectedEpisode;
set selectedTv(int newIndex) {
this._selectedTv = newIndex;
notifyListeners();
}
set selectedSeason(int newIndex) {
this._selectedSeason = newIndex;
notifyListeners();
}
set selectedEpisode(int newIndex) {
this._selectedEpisode = newIndex;
notifyListeners();
}
int get selectedTv => this._selectedTv;
int get selectedSeason => this._selectedSeason;
int get selectedEpisode => this._selectedEpisode;
}
Then your tv shows page becomes:
final selectedItems = Provider.of<CurrentIndexProvider>(context);
FutureBuilder(
future: Provider.of<Data>(context).fetchShows(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
// tvSelected = index; -->we dont need this anylonger
//we set the current show number to the index of the current
//listview item when tapped
selectedItems.selectedSeason=index;
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return SeasonsPage(
//we don't need to pass anything in the constructor again
// selectedTv: tvSelected
);
}));
},
child: Container(
margin: EdgeInsets.all(10.0),
width: 100.0,
color: Colors.orangeAccent,
child: Text(snapshot.data[index].name),
),
);
},
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
your seasons page becomes
final selectedItems = Provider.of<CurrentIndexProvider>(context);
FutureBuilder(
future: Provider.of<Data>(context).fetchShows(),
builder: (context, snapshot) => snapshot.hasData
? ListView.builder(
itemCount: snapshot.data[ selectedItems.selectedTv].content.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: () {
//selectedSeason = index; --> we dont need this any longer
selectedItems.selectedSeason=index;
Navigator.push(context, MaterialPageRoute(
builder: (BuildContext context) {
return EpisodesPage(
//we don't need any parameter in the constructor now
// selectedTv: selectedTv,
// selectedSeason: selectedSeason,
);
}));
},
child: Container(
margin: EdgeInsets.all(10.0),
width: 100.0,
color: Colors.orangeAccent,
child: Text(
snapshot.data[selectedItems.selectedTv].content[index].name),
),
);
},
)
: Center(child: CircularProgressIndicator()),
),
And finally the episodes page becomes
final selectedItems = Provider.of<CurrentIndexProvider>(context);
FutureBuilder(
future: Provider.of<Data>(context).fetchShows(),
builder: (context, snapshot) => snapshot.hasData
? ListView.builder(
itemCount: snapshot.data[selectedItems.selectedTv ].content[selectedItems.selectedSeason]
.episodes.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: EdgeInsets.all(10.0),
width: 100.0,
color: Colors.orangeAccent,
child: Text(snapshot.data[selectedItems.selectedTv]
.content[selectedItems.selectedSeason].episodes[index]),
);
},
)
: Center(child: CircularProgressIndicator()),
),
With this you can have access to the currently selected tv show or seasons or even episodes anywhere within you code by using provider. hope this helped
Am beginner in flutter. I have four widgets with different view i.e. BarChart, LineChart, StackedBarChart and CircularChart. Then i created a List
final List<Widget> widgetList = <Widget>[
BarChartWidget(), LineChartWidget(), StackedBarChartWidget(), CircularChartWidget(),];
How can i iterate through List of this widgets in ListView
body: new ListView.separated(
itemCount: entries.length,
padding: EdgeInsets.all(8.0),
itemBuilder: (BuildContext context, int index) {
return Container(
height: 150,
color: Colors.amber[colorCodes[index]],
child: new widgetList[index],
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
)
);
You were almost there. The issue is:
child: new widgetList[index],
That's not a valid syntax. You cannot "new" widgetList, as it is a variable.
Just do:
child: widgetList[index],
Here's the final syntax:
new ListView.separated(
itemCount: entries.length,
padding: EdgeInsets.all(8.0),
itemBuilder: (BuildContext context, int index) {
return Container(
height: 150,
color: Colors.amber[colorCodes[index]],
child: widgetList[index],
);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
);