Reputation: 11
I use lazycolumn to display amount of images using coil lets say 10 image, when I reach the end of lazycolumn I get 10 more images, but the images are not loaded from the network yet and the the images has crossfade which I don't want, is there a way to make images loading after all new incoming images cached so I can see fully visible images instead of crossfade or place holder...
the thing i want to get is the scroll behavior of social media apps like instagram, when we scroll down to bottom if the items finish we don't see a placeholder or crossfade, instead we see a loading indicator until all data is being cached,it will be visible to us when it is cached, and after it has been cached even if the amount of items that lazy column has are too many we still can see the images at the top (when i scroll bottom and turn back to top I see images are reloaded from network in my case )
@Composable
fun ProductScreen(
viewModel: ViewModel = hiltViewModel()
) {
val products by viewModel.products.collectAsStateWithLifecycle()
val isLoading by viewModel.isLoading.collectAsStateWithLifecycle()
val listState = rememberLazyListState()
val shouldLoadMore = remember {
derivedStateOf {
val totalITemsCount = listState.layoutInfo.totalItemsCount
val lastVisibleItemIndex =
listState.layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0
!isLoading && lastVisibleItemIndex >= totalITemsCount - 1
}
}
LaunchedEffect(shouldLoadMore.value) {
if (shouldLoadMore.value) {
val totalItemCount = listState.layoutInfo.totalItemsCount
viewModel.loadMoreProducts(totalItemCount)
}
}
val context = LocalContext.current
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 16.dp),
state = listState,
verticalArrangement = Arrangement.spacedBy(5.dp)
) {
items(products) { product ->
ProductCard(product, context = context)
}
if (isLoading) {
item {
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
CircularProgressIndicator()
}
}
}
}
}
@Composable
fun ProductCard(product: Product, context: Context) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
.aspectRatio(1f)
.border(1.dp, Color.Blue.copy(alpha = 0.3f), shape = RoundedCornerShape(6.dp))
) {
AsyncImage(
model = ImageRequest.Builder(context)
.data(product.imageUrl)
.crossfade(false)
.build(),
contentDescription = "",
modifier = Modifier.fillMaxSize(),
)
}
}
Upvotes: 1
Views: 246
Reputation: 54
Thanks to Công Hải. This is how you can preload and use the image:
val context = LocalContext.current
val imageLoader = ImageLoader.Builder(context).build()
val imageData = ImageRequest.Builder(LocalContext.current)
.data(imageUrl)
.placeholder(placeholderResourceId) // Image res id which will be used as a placeholder
.error(errorResourceId) // Image res id which will be used if image is not loaded based on any error
.build()
SubcomposeAsyncImage(
model = imageData,
contentDescription = "contentDescription",
imageLoader = imageLoader,
success = { state ->
Image(
modifier = modifier,
painter = state.painter,
contentDescription = "contentDescription",
)
}
Upvotes: 0
Reputation: 5241
to preload logic you can use this code, and make sure it runs success after you append new items to LazyColumn
val imageLoader = Coil.imageLoader(context)
val request = LoadRequest.Builder(context)
.data("your_link")
.target { drawable ->
val bitmap = (drawable as BitmapDrawable).bitmap // bitmap from cache returns
}
.build()
imageLoader.execute(request)
Upvotes: 0