Scroll horizontally in ListView builder within a Future builder - Flutter - flutter

I am trying to create a horizontally scrollable list of cards but it breaks each. I am just not sure where I am going wrong. I tried adding Expandable in several places and I still get errors.
I am hoping this is resolvable or do I need to separate each element within the Container/Column (2nd one).
It is definitely some sort of sizing I am missing but just not able to pinpoint where.
body: SafeArea(
child: Column(
children: [
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(...),
Padding(...),
Padding(...),
SizedBox(...),
Padding(...),
SizedBox(...),
Padding(...),
SizedBox(...),
Container(
height: 200,
color: Colors.blue[200],
child: ListView(
shrinkWrap: true,
physics: ScrollPhysics(),
scrollDirection: Axis.vertical,
children: [
FutureBuilder(
future: getAudioList(),
builder: (context, data) {
if (data.hasError) {
return Center(child: Text("${data.error}"));
} else if (data.hasData) {
var items = data.data as List<MyOtherFunc>;
var categories;
//Split into categories
if (items != null) {
categories = groupBy(
items, (MyOtherFunc ma) => ma.category);
Map<String, List<MindfulAudio>> catMap =
categories;
return new ListView.builder(
padding:
const EdgeInsets.fromLTRB(8, 0, 8, 0),
itemCount: catMap.length,
physics:
const AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, index) {
String key = catMap.keys.elementAt(index);
return Card(
child: ListTile(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
MyFunc(
catMap[key], key),
),
);
},
leading: Icon(icons[index],
size: 25, color: colour[index]),
title: new Text("$key"),
trailing: new IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
MyFunc(
catMap[key], key),
),
);
},
icon: Icon(
FontAwesomeIcons.chevronRight,
color: PINK,
)),
),
);
},
);
}
return Center(
child: CircularProgressIndicator(),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
),
],
),
),
],
),
),
],
),
),

Try this layout
SizedBox(
height: MediaQuery.of(context).size.height,
width : MediaQuery.of(context).size.width,
child: SingleChildScrollView (
child: Column(
children: [
//Other widgets which will scroll vertically in the column
SingleChildScrollView (
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
//Items you wish to scroll horizontally
]
)
),
//Some more widgets if you wish to add below the horizontal scroll
]
)
)
)

Related

When keyboard open/close at that time ChangeNotifierProvider call multiple time

I am facing issue When keyboard open/close at that time ChangeNotifierProvider call multiple time so my full screen reload multiple time. In this widget I have attach video so widget is calling so many times then my instance is fail.
return Scaffold(
backgroundColor: ColorManager.colorBackgroundGray,
body: ChangeNotifierProvider<CreateRouteStep2ViewModel>(
create: (BuildContext context) => modelProvider,
builder: (context, snapshot) {
printValue(label: "ChangeNotifierProvider", value: "");
return Consumer<CreateRouteStep2ViewModel>(
builder: (context, provider, c) {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
provider.viewType == CreateRouteStep2ViewType.map
? SizedBox(
height: 300,
child: GoogleMapForCreateRoute(
modelProvider: modelProvider),
)
: const SizedBox(),
],
),
)
],
),
Expanded(
flex: 1,
child: Container(
color: ColorManager.colorWhite,
child: SingleChildScrollView(
child: ListView.builder(
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.only(top: 10),
itemCount: provider.listRouteName.length,
itemBuilder: (BuildContext context, index) {
return CreateStepsItem(
routeModel:
provider.listRouteName[index],
modelProvider: modelProvider,
index: index,
removeIndex: () {
// Todo Remove index from marker pin and location array.
modelProvider
.removeIndexFromPinAndList(index);
},
edtLocationNameFocus: () {
modelProvider.focusMap(index);
},
edtAudioFocus:
(mainPosition, subPosition) {
modelProvider.focusAudioComponent(
index, subPosition);
},
edtVideoFocus:
(mainPosition, subPosition) {
modelProvider.focusVideoComponent(
index, subPosition);
},
);
},
scrollDirection: Axis.vertical,
),
),
)),
Visibility(
visible:
MediaQuery.of(context).viewInsets.bottom == 0,
child: Align(
alignment: Alignment.bottomCenter,
child: Padding(
padding: const EdgeInsets.only(
left: 24.0, right: 24.0, bottom: 20.0),
child: CommonButton(
onPressed: () {},
lable: AppStrings.constTourSpichern,
isEnable: false,
),
),
),
)
],
),
),
const SizedBox(
height: 20,
)
],
),
);
});
}),
);
Is there any widget behaviour is attach with keyboard?. If any one know that then please let me know.

Adjusting the grid layout

I have been trying to add the code below within the card grid view. The text widget is just for testing purposes. When I tap on the card I want to perform the action that is written for the iconButton onPressed method.
Expanded(
child: StreamBuilder(
stream:
FirebaseFirestore.instance.collection('location').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: snapshot.data?.docs.length,
itemBuilder: (context, index) {
return ListTile(
title:
Text(snapshot.data!.docs[index]['name'].toString()),
subtitle: Row(
children: [
Text(snapshot.data!.docs[index]['latitude']
.toString()),
SizedBox(
width: 20,
),
Text(snapshot.data!.docs[index]['longitude']
.toString()),
],
),
trailing: IconButton(
icon: Icon(Icons.directions),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) =>
MyMap(snapshot.data!.docs[index].id)));
},
),
);
});
},
)),
Here is the card grid
return Scaffold(body: Container(decoration: BoxDecoration(
image:DecorationImage(
image: AssetImage("assets/background.jpg"), fit: BoxFit.cover),),child: Container(
margin: const EdgeInsets.only(top: 120.0),
child: GridView(
physics: BouncingScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: events.map((title){
return GestureDetector(
child: Card(
elevation: 0,
color: Colors.transparent,
margin: const EdgeInsets.all(13.0),
child: getCardByTile(title)
),
onTap: () {
Fluttertoast.showToast(msg: title);
},
);
}).toList(),
),
),));
Here is the CardByTile() method used above.
getCardByTile(String title) {
String img = "";
if(title == "Navigation") {
img = "assets/navi.png";
}
if(title == "Current location") {
img = "assets/currentloc.png";
}
if(title == "Enable live location") {
img = "assets/track.png";
}
if(title == "Stop live location") {
img = "assets/stoplive.png";
}
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Center(
child: new Stack(
children: <Widget>[
new Image.asset(
img,
fit: BoxFit.contain,
//width: 80.0,
//height: 80.0,
)
],
),
)
]
);
}
and the event list.
List<String> events = [
"Navigation",
"Current location",
"Enable live location",
"Stop live location"
];

How to make ListView Scrollable in flutter

Newbie here. I have managed to implement a ListView that simply displays images. However the ListView isn't scrollable. I have attempted to wrap it in SingleChildScrollView, have added physics to AlwaysScrollableScrollPhysics and also tried removing Expand widgets from the layout. What am I missing?
LAYOUT
return Scaffold(
body: SingleChildScrollView(
child: Column(children: [
SizedBox(
height: 6,
),
StreamBuilder(
stream: ref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
lists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
lists.add(values);
});
return new ListView.builder(
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String imageurl = lists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullScreenImageViewer(
imagurl: imageurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Container(
width: 400,
child: Image(
image:
NetworkImage(lists[index]["image"]),
),
),
),
),
),
],
);
},
);
}
return Container();
},
),
]),
),
);
You can remove the single child scroll view, i believ the problem here is because you are using a column and the listview is not expanding to the whole screen. If you want to make sure the listview occupy the all the space remaining you can use the Flex and expanded widget.
Flex can work like a column or row depending on which direction you are providing it with. anything that is placed here behave exactly like when they is placed in the column or row except for Expanded, as they fill the remainning space.
I've changed your code a bit here to accomodate the Flex and Expanded widget (you just need to readd your logic and the streambuilder to make it work)
return Scaffold(
body: Flex(direction: Axis.vertical, children: [
const SizedBox(
height: 6,
),
Expanded(
// Change the children to stream builder if neccesary
child: ListView.builder(
shrinkWrap: true,
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Card(
margin: const EdgeInsets.all(2),
elevation: 20,
child: GestureDetector(
onTap: () {
// ACTION HERE
},
child: const Padding(
padding: EdgeInsets.all(5),
child: Image(
image: NetworkImage("https://picsum.photos/200/300"),
),
),
),
),
],
);
},
),
)
]),
);
There's a property within listView() that tells it which irection the overflow is so as to scroll. Set it to
scrollDirection: Axis.horizontal

How To Add TabBar with Horizontal And Vertical ListView In One Tab Scrolling In Respective Directions

Flutter newbie here if my code looks too messy. Managed to figure out a few basic layouts and have implemented a TabBar. In 2nd Tab(COMICS). I have a horizontal ListView and a vertical one. I just can't figure out how to make the horizontal ListView scroll without changing tabs.
How i create the tabs:
return NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
title: Text('NestedScrollView'),
)
];
},
body: Scaffold(
appBar: AppBar(
toolbarHeight: 40,
centerTitle: true,
backgroundColor: Color(0xFFb92136),
title: Text('Kata Kata African Cartoons'),
// actions: [
// IconButton(onPressed: () {}, icon: Icon(Icons.search)),
// IconButton(onPressed: () {}, icon: Icon(Icons.more_vert))
// ],
bottom: TabBar(
controller: tabController,
tabs: [
Tab(
text: "VIDEOS",
),
Tab(
text: "COMICS",
),
Tab(
text: "MAGAZINE",
),
],
),
),
body: TabBarView(
controller: tabController,
children: [
VideosTab(),
ComicsTab(),
Magazines(),
],
),
));
Main body of comics tab
return Column(children: [
Container(child: Card(
elevation: 20,
child: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(5),
child: Text("Katakata Long Comics"))
]),
Card(
child: StreamBuilder(
stream: ref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
lists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
lists.add(values);
});
return Container(
height: 200,
child: new ListView.builder(
physics: const NeverScrollableScrollPhysics(),
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: lists.length,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String pdfurl = lists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFViewer(
url: pdfurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Column(
children: [
Container(
height: 100,
width: 100,
child: Image(
image:
NetworkImage(lists[index]["image"]),
),
),
Text(lists[index]["name"]),
],
),
],
),
),
),
);
},
),
);
}
return Container(child: Text("Add Plants"));
},
),
),
],
),
)),
Container(child: Card(
elevation: 20,
child: Column(
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: EdgeInsets.all(5),
child: Text("Continuous Humour"))
]),
Card(
child: StreamBuilder(
stream: secref.onValue,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData &&
!snapshot.hasError &&
snapshot.data.snapshot.value != null) {
seclists.clear();
DataSnapshot dataValues = snapshot.data.snapshot;
Map<dynamic, dynamic> values = dataValues.value as Map;
values.forEach((key, values) {
seclists.add(values);
});
return new ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: seclists.length,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: EdgeInsets.fromLTRB(2, 2, 2, 2),
elevation: 20,
child: GestureDetector(
onTap: () {
String pdfurl = seclists[index]["image"];
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PDFViewer(url: pdfurl,
),
));
},
child: Padding(
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
height: 200,
width: 400,
child: Image(
image:
NetworkImage(seclists[index]["image"]),
),
),
Text(seclists[index]["name"]),
],
),
),
),
);
},
);
}
return Container(child: Text("Add Plants"));
},
),
),
],
),
)),
]);
You have NeverScrollableScrollPhysics() defined as the physics for your listviews. That means they won't scroll even when there is no tabview around them. Also they won't absorb the scroll event and defer them to the tabview.

put pageview inside listview flutter

I am trying to learn how to create complex UI elements in flutter and faced this problem. Suppose I want to put a pageview in my listView and display the same items as in the horizontal scrolling list. Is there any way to do this?
Here is my code of build method with listview:
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: _catList.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
Card(
child: ListTile(
title: Text(_catList[index].name),
),
),
IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(
child: Column (
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text ('ID: ${_catList[index].id}'),
Text ('Country code: ${_catList[index].countryCodes}'),
Text ('Temperament: ${_catList[index].temperament}'),
Text ('Origin: ${_catList[index].origin}')
],
)
),
Expanded(
child: Card(
child: Text(_catList[index].description),
),
)
],
),
),
Container (
child: PageView.builder (itemBuilder: (context, index) {
} ),
)
],
),
);
},
);
}
As i under stand you want to add PageView in side ListView. So your ListView scroll in vertical direction and your PageView scroll in horizontal direction. If i am not wrong then below is my code to do the same things.
I have made my List which contain multiple List like below.
var modelListOne = ["model_1_1.png", "model_1_2.png",];
var modelListTwo = ["model_2_1.png", "model_2_2.png",];
var modelList = [modelListOne, modelListTwo,];
return ListView.builder(
itemCount: modelList.length,
itemBuilder: (context, index) {
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => YOURPAGE());
},
child: Card(
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Container(
height: 350,
width: double.maxFinite,
child: PageView.builder(
itemCount: modelList[index].length,
scrollDirection: Axis.horizontal,
itemBuilder: (context, pageIndex) {
return Container(
height: 300,
width: double.maxFinite,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"assets/images/${modelList[index][pageIndex]}",
),
fit: BoxFit.cover)),
);
}),
)),
),
);
});
Make changes regarding to your requirements. Thanks.