Comments (8)
I was initially thinking that we could change the internal loading logic to add a debounce on the Loading
state, but the more I think about this, the more than feels like a UI thing.
The way I'm thinking about this is that we wrap the 'loading' content with something like this:
@Composable
fun WithDelay(
delayMs: Long,
content: @Composable () -> Unit
) {
var visible by remember { mutableStateOf(false) }
LaunchedEffect(Unit) {
delay(delayMs)
visible = true
}
if (visible) content()
}
You can then do:
CoilImage(
// ...
loading = {
// choose whatever delay works, 500ms is a good initial value
WithDelay(500) {
Text("Loading...")
}
}
)
This matches the behavior of ContentLoadingProgressBar
and feels right to me.
I haven't decided whether to bake this into the 'simple' CoilImage
etc yet. I don't really want to add yet-another-parameter to control the delay, and the integration is pretty simple to do in clients.
from accompanist.
I wired that up, and it certainly works. Though for the scenario I described, you'd want to to use withDelay
in the Empty
state instead of the Loading
state. it's a flash of the Empty
state that I'm trying to eliminate. But, it could be useful in the Loading
state as well. In cases where the image gets loaded fast, you could prevent a "flash" of the Loading
state composable.
That also lends to the idea of NOT adding the delay as a parameter on the simple CoilImage
composable. Different use cases might require delays on different states. As you mentioned, it's simple to wire up. It took me 2 minutes, and I even had to roll my own withDelay
composable. If a client wants/needs a delay on a certain state, it's easy to setup.
from accompanist.
Ahhh, I misread the scenario 🤔
This makes me think that the Empty
state is actually useless, since we always transition to Loading
after the first composition + layout. The thrashing has no benefit.
One thought is to merge those into a single Pending
state.
from accompanist.
yeah, when I looked at it originally, I kind of wondered if you could just initialize it in the Loading
state. Merging the two might do the trick. One thing the Empty
state IS useful for is supplying a drawable resource to use for @Preview
composables in Android Studio. That's what led me down this rabbit hole in the first place. It might be useful to keep the Empty
state around, but only use it in a case where the data
parameter is null or otherwise empty.
from accompanist.
Thanks for the info! I think starting from Loading
is the simplest solution, and we'll treat Empty
as a 'result'/end state instead.
Can you attach an example of what you're doing for @Preview
s? I think we can fix that separately rather than relying on Empty
.
from accompanist.
As a learning effort, I'm building a pretty basic app to consume a feed from a blog that I read and show posts, very similar to the JetNews sample app. The top post in the list on the home screen is "featured" and shows an image. My Composable for the top post looks like this:
@Composable
fun FeaturedPost(post: Post) {
Column {
PostImage(post.imageUrl)
PostItem(post)
}
}
@Composable
fun PostImage(url: String, modifier: Modifier = Modifier.fillMaxWidth().aspectRatio(1.78F)) {
CoilImage(
data = url,
modifier = modifier) { imageState ->
when (imageState) {
is ImageLoadState.Success -> {
MaterialLoadingImage(
result = imageState,
fadeInEnabled = true,
fadeInDurationMs = 600,
contentScale = ContentScale.Crop
)
}
is sImageLoadState.Empty -> {
// Use this image in the Preview in Android Studio
Image(asset = vectorResource(id = R.drawable.ic_uk_logo),
modifier = Modifier.fillMaxSize().padding(16.dp),
contentScale = ContentScale.Fit)
}
}
}
}
The Post
model (instances of which are created from the response of an API call) contains several fields, one of them being an image url:
data class Post(url: String, imageUrl: String, title: String, content: String) // etc, etc
To Preview a featured post, I create a mock Post, and call the FeaturedPost composable:
@Preview("Featured Post")
@Composable
fun PreviewPost() {
val post = Post(
url = "postUrl",
image = "https://kentuckysportsradio.com/wp-content/uploads/2018/09/MSU-8843.jpg",
title = "Featured Post Title",
description = "The post preview is a a short description of the content that is in the main post",
author = "Brad Ball",
postDate = Date().time,
content = "Main post content")
ThemedPreview() {
FeaturedPost(post)
}
}
from accompanist.
Thanks! Yeah, I think we can do better here when in preview.
from accompanist.
Opened #150 for this.
from accompanist.
Related Issues (20)
- Stop [Permissions]
- Incorrect behaviour when bottom sheet is closed by clicking on its background HOT 3
- [Navigation Material] HOT 1
- [BottomSheetNavigator] NullPointerException (race-condition?) when using back button HOT 6
- [WebView] Doesn't save state when recycled in a LazyColumn HOT 2
- [WebView] Question about backwards writes HOT 5
- Vector animation is broken with newer libraries HOT 5
- False positive deprecation message on pagerTabIndicatorOffset variant HOT 2
- onPermissionsResult isn't triggered on POST_NOTIFICATIONS permission request (API 33). HOT 2
- [Test Harness] Deprecate with replacement of `DeviceConfigurationOverride`
- Incorrect deprecation of pagerTabIndicatorOffset HOT 1
- [Permissions] Gradle update crashing permission request and the app HOT 8
- Crash when using ProgressIndicator with `accompanist-permissions` 0.34.0 HOT 1
- [Navigation Material] Crash in BottomSheetNavigator when user goes back HOT 3
- [Navigation Material] Status bar not scrimmed when bottom sheet is shown HOT 1
- [LazyColumn] scroll observation scope does not exist HOT 2
- [Feature request] LazyTable with nested scrolling support HOT 1
- [Navigation Material] Edge to edge jumping bug when migrating from 1.1.2 to 1.2.0. HOT 1
- [Navigation Material] BackHandler is not triggered after Activity stop+start HOT 1
- [Navigation Material] DisposableEffect onDispose is not called at the right time for bottom sheet HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from accompanist.