posts: use a shimmering animation for loading posts

Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
Harsh Shandilya 2021-03-08 16:22:39 +05:30
parent 00c6cbd7a6
commit 08c511f854
No known key found for this signature in database
GPG key ID: 366D7BBAD1031E80
4 changed files with 124 additions and 43 deletions

View file

@ -1,41 +0,0 @@
package dev.msfjarvis.lobsters.ui.posts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import dev.msfjarvis.lobsters.R
import dev.msfjarvis.lobsters.util.IconResource
@Composable
fun EmptyList(saved: Boolean) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
if (saved) {
IconResource(
R.drawable.ic_favorite_border_24px,
tint = Color(0xFFD97373),
modifier = Modifier.padding(16.dp),
contentDescription = stringResource(R.string.add_to_saved_posts),
)
Text(stringResource(R.string.no_saved_posts))
} else {
IconResource(
R.drawable.ic_sync_problem_24px,
modifier = Modifier.padding(16.dp),
contentDescription = stringResource(R.string.remove_from_saved_posts),
)
Text(stringResource(R.string.loading))
}
}
}

View file

@ -27,7 +27,11 @@ fun HottestPosts(
val urlLauncher = LocalUrlLauncher.current
if (posts.loadState.refresh == LoadState.Loading) {
EmptyList(saved = false)
LazyColumn {
items(15) {
LoadingLobstersItem()
}
}
} else {
LazyColumn(
state = listState,

View file

@ -1,13 +1,24 @@
package dev.msfjarvis.lobsters.ui.posts
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import dev.msfjarvis.lobsters.R
import dev.msfjarvis.lobsters.data.local.SavedPost
import dev.msfjarvis.lobsters.ui.urllauncher.LocalUrlLauncher
import dev.msfjarvis.lobsters.util.IconResource
import dev.msfjarvis.lobsters.util.asZonedDateTime
@OptIn(ExperimentalFoundationApi::class)
@ -21,7 +32,19 @@ fun SavedPosts(
val urlLauncher = LocalUrlLauncher.current
if (posts.isEmpty()) {
EmptyList(saved = true)
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
IconResource(
R.drawable.ic_favorite_border_24px,
tint = Color(0xFFD97373),
modifier = Modifier.padding(16.dp),
contentDescription = stringResource(R.string.add_to_saved_posts),
)
Text(stringResource(R.string.no_saved_posts))
}
} else {
LazyColumn(
state = listState,

View file

@ -0,0 +1,95 @@
package dev.msfjarvis.lobsters.ui.posts
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.keyframes
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.absoluteOffset
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredSize
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@Composable
fun LoadingLobstersItem() {
val infiniteTransition = rememberInfiniteTransition()
val alpha by infiniteTransition.animateFloat(
initialValue = 0.2f,
targetValue = 1f,
animationSpec = infiniteRepeatable(
animation = keyframes {
durationMillis = 1000
0.7f at 500
},
repeatMode = RepeatMode.Reverse
)
)
val color = Color.LightGray.copy(alpha = alpha)
Surface(
modifier = Modifier.height(70.dp),
) {
Row(
modifier = Modifier.padding(start = 12.dp, end = 12.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Column(
verticalArrangement = Arrangement.SpaceEvenly,
) {
Box(
modifier = Modifier
.fillMaxWidth()
.requiredHeight(12.dp)
.background(color)
.padding(8.dp),
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier
.absoluteOffset(y = 12.dp),
) {
Box(
modifier = Modifier
.requiredSize(30.dp)
.background(color = color, shape = CircleShape),
)
Box(
modifier = Modifier
.requiredHeight(12.dp)
.requiredWidth(40.dp)
.absoluteOffset(x = 12.dp)
.background(color),
)
}
}
}
}
}
@Preview
@Composable
fun ShimmerListPreview() {
LazyColumn {
items(10) {
LoadingLobstersItem()
}
}
}