I have an image grid "StaggeredImageGrid" and what I want is that when I tap on one of those images, that image should show up at the top of the screen. To put it in other words, you all know Instagram posts, right. When you go to your profile page and click one of the images from the grid view, exactly that image pops up on the top of your screen and you can scroll up and down to see the other images as well.
child: new StaggeredGridView.countBuilder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 4,
mainAxisSpacing: 3,
crossAxisSpacing: 3,
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(2, index.isEven ? 2 : 3),
itemCount: _posts.length,
itemBuilder: (BuildContext context, int index) {
Post post = _posts[index];
List<PostView> postViews = [];
_posts.forEach((post) {
postViews.add(PostView(
currentUserId: widget.currentUserId,
post: post,
author: _profileUser,
));
});
return GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SingleChildScrollView(
child: ListView.builder(
padding: EdgeInsets.only(top: 0),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: postViews.length,
itemBuilder:
(BuildContext context, int index) {
return Column(children: postViews);
},
),
),
),
),
child: Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(7)),
child: Image(
image:
CachedNetworkImageProvider(post.imageUrl),
fit: BoxFit.cover,
),
),
),
);
},
),
When I am clicking on one of the images, I am getting the list of images starting from beginning instead of that exact image.
Try to implement scroll_to_index listview in your second page when pressing the image of your grid, when you press image, pass index to second page and jump to that index image after build:
ListView(
scrollDirection: scrollDirection,
controller: controller,
children: randomList.map<Widget>((data) {
final index = data[0];
final height = data[1];
return AutoScrollTag(
key: ValueKey(index),
controller: controller,
index: index,
child: Text('index: $index, height: $height'),
highlightColor: Colors.black.withOpacity(0.1),
);
}).toList(),
)
Related
This question already has answers here:
How to Move bottomsheet along with keyboard which has textfield(autofocused is true)?
(24 answers)
Closed 6 months ago.
I am using a SingleChildScrollView with a ListView in a showModalBottomSheet but the keyboard is hidding the field when the user is filling it.
showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
isDismissible: false,
builder: (context) {
return SafeArea(
child: Container(
decoration: ...
child:Column(
children:[
Text("...),
Expanded(
child: SingleChildScrollView(
child: ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return TextField(...)
]);
},
separatorBuilder: (BuildContext context, int index) => const Divider(),
),
),
),
Button(...),
]),
));
}
Wrap your modal builder with SingleChildScrollView and add padding to it like this:
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
full example:
showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
isDismissible: false,
builder: (context) {
return SingleChildScrollView(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
decoration: BoxDecoration(
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(8.0),
topRight: const Radius.circular(8.0)),
),
padding: EdgeInsets.only(left: 16, right: 16, bottom: 16),
child: Column(
children: [
ListView.separated(
// padding: EdgeInsets.zero,
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return TextField(
decoration: InputDecoration(hintText: 'text'),
);
},
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
),
ElevatedButton(
onPressed: () {
_showBottom(context);
},
child: Text('button')),
],
),
),
);
})
when keyboard is close:
when it is open:
You can add the SingleChildScrollView up right after the safearea widget.
Now, you will get an error because the children does not have a boundary height.
You can use the height of the screen to set the container height.
Then add padding to the SingleChildScrollView matching the keyboard height
Showing lines with significant changes below
showModalBottomSheet(
context: context,
isScrollControlled: true,
enableDrag: true,
isDismissible: false,
builder: (context) {
return SafeArea(
child: SingleChildScrollView(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: MediaQuery.of(context).size.height,
child: Column(children: [
TextField(),
Expanded(
child: ListView.separated(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: 10,
itemBuilder: (BuildContext context, int index) {
return TextField();
},
separatorBuilder:
(BuildContext context, int index) =>
const Divider(),
),
),
TextField(),
]),
),
),
);
});
I need ripple effect when tap image like facebook my day. Use Ink.image for grid view image not work in my code. I want to ripple when on tap action trigger on my image but my code only work for pressing. Also add the Material widget to the parent of Ink.image widget. Please solve me.
This is my code.
Expanded(
child: GridView.builder(
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
controller: _scrollController,
padding: EdgeInsets.all(8.0),
itemCount: _agentsList.length,
shrinkWrap: true,
physics: ClampingScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return Stack(
children: [
Container(
margin: EdgeInsets.all(margin),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(19.0)),
child: Material(
clipBehavior:Clip.hardEdge,
child: Ink.image(
image: CachedNetworkImageProvider(
_agentsList[index].agentPhoto,
),
fit: BoxFit.cover,
child: InkWell(
splashFactory:InkSplash.splashFactory,
onTap: () {
widget.viewType =
Agent.current != null
? "hello"
: "";
Navigator.of(context)
.pushNamed('/ProfileView',
arguments: {
"agent":
_agentsList[index]
});
},
),
)
),
),
),
],
);
}))
is it possible to put the GridView into Carousel in flutter like this??
i don't understand about the carousel but i learn it and i get the Carousel more useful then grid-view if i follow my design?
this is my GridView Code
Container(
margin: EdgeInsets.all(2),
child: new StaggeredGridView.countBuilder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 2,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius:
BorderRadius.all(Radius.circular(12))),
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(12)),
child: FadeInImage.memoryNetwork(
placeholder: kTransparentImage,
image: imageList[index],
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (index) {
return new StaggeredTile.count(
1, index.isEven ? 1 : 2);
}),
)
Yes you can simply use StaggeredGridView inside CarouselSlider. About the UI you are trying to archive, the first image(index=0) will be the large one. If we try to simplify the UI by dividing the pattern, we can see there are three GridItem can think as single bloc, and to get the left one larger we need to use StaggeredTile.count(1, index % 3 == 0 ? 2 : 1);. In this case staggeredTileBuilder will be
staggeredTileBuilder: (index) {
return StaggeredTile.count(1, index % 3 == 0 ? 2 : 1);
}),
Widget
return Scaffold(
body: CarouselSlider(
items: [
Container(
margin: EdgeInsets.all(2),
child: StaggeredGridView.countBuilder(
// physics: NeverScrollableScrollPhysics(), // it can use scollable if upper widget dont cause any issue
shrinkWrap: true,
crossAxisCount: 2,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
itemCount: imageList.length,
itemBuilder: (context, index) {
return Container(
decoration: const BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(12))),
child: ClipRRect(
borderRadius:
const BorderRadius.all(Radius.circular(12)),
child: Container(
color: Colors.amber,
alignment: Alignment.center,
child: Text(index.toString()),
)
// FadeInImage.memoryNetwork(
// // placeholder: kTransparentImage,
// image: imageList[index],
// fit: BoxFit.cover,
// ),
),
);
},
staggeredTileBuilder: (index) {
return StaggeredTile.count(1, index % 3 == 0 ? 2 : 1);
}),
),
Container(
color: Colors.deepPurple,
),
Container(
color: Colors.deepOrange,
),
],
options: CarouselOptions(aspectRatio: 1, viewportFraction: 1),
),
);
I would say practice with Text Widget with viewing index to understand what and how widget is changing and set the logic inside staggeredTileBuilder to get the outcome. And about the imagePath you aren't passing string value on that, debug/print the path to verify it.
For more about
carousel_slider
flutter_staggered_grid_view
Staggered Grid View on yt you can find many by searching
I need help replacing the first element of the StaggeredGridView with other Widget, say, Container. I have been trying to change it for hours but couldn't find a way.
Padding(
padding: const EdgeInsets.all(5.0),
child: new StaggeredGridView.countBuilder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
crossAxisCount: 4,
mainAxisSpacing: 3,
crossAxisSpacing: 3,
itemCount: posts.length,
itemBuilder: (BuildContext context, int index) {
Post post = posts[index];
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(7)),
child: Image(
image: AssetImage(post.imageUrl),
fit: BoxFit.cover,
),
),
);
},
staggeredTileBuilder: (int index) =>
new StaggeredTile.count(2, index.isEven ? 3 : 2),
),
),
Above is the code for the grid I am using.
Thank you.
itemBuilder will generate a widget with the function provided, thus you could just add an if statement to build one or other widget:
itemCount: posts.length + 1, // added one item on the beginning
itemBuilder: (BuildContext context, int index) {
if (index == 0) {
return Container(
child: // your widget
);
} else {
Post post = posts[index - 1]; // remember that you have +1 on your index
return Container(
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.all(Radius.circular(15))),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(7)),
child: Image(
image: AssetImage(post.imageUrl),
fit: BoxFit.cover,
),
),
);
}
},
I have a List in my Flutter app in which I am trying to resize the leading image to ressemble the List as shown below. I can't however understand how to fix the aspect ratio to have the height equal to the width and make the box a square.
This is my code for the ListView:
Expanded(
child: ListView.builder(
itemExtent: 100.0,
// padding: EdgeInsets.all(10.0),
itemCount: filteredUsers.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(4.0)),
child: Image.network(
"https://d36tnp772eyphs.cloudfront.net/blogs/1/2018/02/Taj-Mahal.jpg",
),
),
title: Text("Taj Mahal"),
subtitle: Text("India"));
},
),
),
This is what it looks like:
And this is what I'm trying to achieve:
To create a square crop of the image on your ListTile, you can use the AspectRatio widget to define the child's aspect ratio as (1 / 1) to make a square, then set Image.network fit to BoxFit.cover.
ListView.builder(
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: AspectRatio(
aspectRatio: 1,
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(4.0)),
child: Image.network(
'https://d36tnp772eyphs.cloudfront.net/blogs/1/2018/02/Taj-Mahal.jpg',
fit: BoxFit.cover,
),
),
),
title: Text('Title $index'),
subtitle: Text('Subtitle $index'),
);
},
),