GestureDetector on ListView.builder in Flutter - flutter

I am trying to add a GestureDetector on my ListView widget which contains Images but it does not seem to work. A similar question has been asked about it before but that did not help either.
Here is my code:
ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext ctx, int index) {
return Container(
width: 160,
child: Card(
child: Wrap(
children: <Widget>[
GestureDetector( onTap: () => Print_on_layout(index),
child: Image.network(a[index], fit: BoxFit.fill,)
)
],
),
),
);
},
itemCount: a.length,
),

I suppose this has something to do with the wrap Widget, which might be messing with the space where the tap can be detected. Try removing it. If that doesn't work, please tell us if you get an error.

Use gesturedetector as a parent of the container not on image.
as in the list you are only returning a single widgit so you should container with gesture detector.
Try this code:
ListView.builder(
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext ctx, int index) {
return
GestureDetector(onTap: () => Print_on_layout(index),
child: Container(
width: 160,
child: Card(
child: Wrap(
children: <Widget>[
Image.network(a[index], fit: BoxFit.fill,)
],
),
),
),
);
},
itemCount: a.length,
),

Related

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

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.

Flutter : Can't get correct size of Card that contain row

I created a card and set a width of container to 300 but i get the card with a width more than 300
return Card(
margin: EdgeInsets.symmetric(horizontal:5,vertical: 10),
child: InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (BuildContext context) =>
CourseInfoPage(widget.courseId)));
},
child: Container(
width: 300,
height: 200,
color:Colors.yellow,
child: Row(
children: <Widget>[
// courseText(context, course, 180),
// courseImage(course, 150),
Container(width: 100,color:Colors.red),
Container(width:200,color: Colors.green,)
],
),
),
),
);
and when i get it inside ListView like this
Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
child: Selector<CategoriesModel, List<CourseModel>>(
selector: (buildContext, model) => model.getCoursesByCategory(categoryName),
builder: (context, value, child) => value == null
? CircularProgressIndicator()
: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: value.length,
itemBuilder: (BuildContext context, int index) {
return CourseCard(value[index].courseId);
},
),
),
),
I want the card to be exactly 300 and one container to 100 and an other to 200 which make it to be 300 but as you can see in the below screenshot i get this extra yellow space
the problem is in the Listview widget. Listview expands its children. To prevent this from happening, you need to wrap your CourseCard inside an Align widget and give it an alignment. check the following code. also, check this answer for more information.
ListView.builder(
scrollDirection: Axis.vertical,
itemCount: 2,
itemBuilder: (BuildContext context, int index) {
return Align(
alignment: Alignment.center,
child: CourseCard(value[index].courseId),
),
);
},
),

Flutter Scroll Carousel above listview.builder

I'd like to add carousel above in listview.builder but the scrolling only happens below in carousel, and the carousel is fixed
// scroll carousel here
new Expanded(
child: new ListView.builder(
itemCount: 4,
itemBuilder: (BuildContext context, int index) {
return itemFeed(context: context, index: index);
}
)
)
You can use a Column to achieve this. Remember to wrap the ListView.builder with a Expanded widget inside the Column.
Example -
Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
height: 100.0,
width: double.infinity,
child: Text('Fixed Box'),
color: Colors.pink,
),
Expanded(
child: ListView.builder(
itemBuilder: (context, index) => Text("Index - " + index.toString()),
itemCount: 100,
),
)
],
)

How to implement multiple horizontal lists inside a column

I want to implement multiple horizontal lists that contain cards with some details, and now all i get is just white screens(without errors)
This is my code:
Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 50,
itemBuilder: (BuildContext context, int index) {
Card(
child: Column(
children: <Widget>[
Text('fsfssffs'),
],
),
);
},
),
),
SizedBox(
height: 20.0,
),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 50,
itemBuilder: (BuildContext context, int index) {
Card(
child: Column(
children: <Widget>[
Text('fsfssffs'),
],
),
);
},
),
),
],
),
);
I want to achieve something like the facebook stories
Use => on List itemBuilder to return the items:
Scaffold(
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 50,
itemBuilder: (BuildContext context, int index) =>
Card(
child: Column(
children: <Widget>[
Text('fsfssffs'),
],
),
);
},
),
),
SizedBox(
height: 20.0,
),
Expanded(
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 50,
itemBuilder: (BuildContext context, int index) =>
Card(
child: Column(
children: <Widget>[
Text('fsfssffs'),
],
),
);
},
),
),
],
),
);
You were not returning any widget from your itemBuilder method which is why you were unable to see anything on screen.
Basically, there are 2 solutions for this, I am giving you idea using a build() method you can do it in your itemBuilder.
(1) Use => (fat arrow notation)
Example:
Widget build(context) => Text("Hi");
(2) Use return.
Widget build(context) {
return Text("Hi");
}