Reputation: 3859
Lets say you have a ListView
of variable height:
Container
with a mix of text and images. As such, the list items are of variable height. Sometimes no images. The text renders immediately as expected, but the images may take time to retrieve and render on screenCachedNetworkImage
ListView
automatically scrolls to item#11 (using ensureVisible
technique)At this point, when one of the network images above your position load up, the entire ListView will be pushed and you will no longer be looking at Item #11, rather somewhere randomly higher up
I considered initiating a new scroll in a callback after each image loads, however, due to network speeds, usually the listview scroll will finish before all the images load. If there are a lot of images, the images could take time to load, so it would be unreasonable to initiate a new scroll each time a new image is loaded, the screen just keeps scrolling forward every few seconds. It becomes dizzying and annoying.
Alternatively, the scrollview could jumpTo a new position as soon as the image loads, but I'm imagining there would be a slight delay between the two events and the user perceive a small "glitch" as the image loads and the listview immediately jumps to offset the image load. Even using a Future.microtask
there is a very small perceptible 'glitch' as the image loads and the jumpto fires
It would be most preferable to have the listview expand the content upward somehow, so that the users current scroll position is maintained, as far as they are concerned.
Is it possible to have the ListView
keep its position as the images load?
Upvotes: 1
Views: 1060
Reputation: 2202
Try as follows:
ListView.builder(
shrinkWrap: true,
itemCount: images.length,
itemBuilder: (ctx, i) {
return Column(children: [
ButtonItems(i),
const SizedBox(height: 10),
]);
}));
Button Items class
class ButtonItems extends StatefulWidget {
final int i;
ButtonItems(this.i);
@override
_ButtonItems createState() => _ButtonItems();
}
class _ButtonItems extends State<ButtonItems> {
var images = [
"https://opengraph.githubassets.com/2ddb0ff05ef9ccfce35abb56e30d9c5068e01d1d10995484cfd07becee9accf7/dartpad/dartpad.github.io",
null,
"https://opengraph.githubassets.com/2ddb0ff05ef9ccfce35abb56e30d9c5068e01d1d10995484cfd07becee9accf7/dartpad/dartpad.github.io"
];
@override
Widget build(BuildContext context) {
print(images[widget.i]);
return Container(
height: 50,
color: Colors.grey,
child: Row(children: [
AspectRatio(
aspectRatio: 3 / 2,
child: images[widget.i] == null
? Container()
: Image.network(images[widget.i]!, fit: BoxFit.cover),
),
Text("Title " + widget.i.toString()),
]));
}
}
Upvotes: 0
Reputation: 157
Images are of variable height
To overcome this, Either we take the image size or aspect ratio of the image while storing the image along with other data.
While retrieving data, along with other text data we will receive the aspect ratio or height for the image.
I would use the same height or ratio and show placeholder image till images are loaded.
CachedNetworkImage(
imageUrl: countryList[index].flagUrl,
height: 60, // Set your height according to aspect ratio or fixed height
width: 60,
fit: BoxFit.cover,
placeholder: (_, __) => Container(
alignment: Alignment.center,
height: 60, // Set your height
width: 60,
color: Colors.red.withAlpha(80),
child: Text(
countryList[index].name[0],
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
),
)
Image must be of specific aspect ratio I believe. You can define height according to aspect ratio.
Upvotes: 0
Reputation: 619
Animated container, might help you. It can adjust the height automatically, depending on the height u provide in builder.
Also you can use this answer to determnin image height and width in rnutime.
Upvotes: 0
Reputation: 1068
Assuming you have a predefined size for your images, you can wrap the image in a SizedBox()
. This way your list will always have the same height and your items won't get pushed around.
EDIT: Since your images are of variable size, I would probably animate to the desired location on every image load.
CachedNetworkImage has a callback
imageBuilder: (context, imageProvider) {
/// Animate to desired index
return Image(image: imageProvider);
}
Upvotes: 1