Fix some animation issue

This commit is contained in:
Thomas Andres Gomez 2021-05-14 14:40:56 +02:00
parent 90d6c4bd65
commit befb235b8b
7 changed files with 61 additions and 18 deletions

View file

@ -1,5 +1,6 @@
package com.pixelized.biblib.ui.composable.pages package com.pixelized.biblib.ui.composable.pages
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
@ -17,6 +18,7 @@ import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.focusModifier
import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
@ -43,9 +45,13 @@ fun DetailPageComposable(
booksViewModel: IBooksViewModel = viewModel<BooksViewModel>(), booksViewModel: IBooksViewModel = viewModel<BooksViewModel>(),
bookId: Int bookId: Int
) { ) {
val book by booksViewModel.getBookDetail(bookId).observeAsState() Box(
book?.let { Modifier.fillMaxWidth().fillMaxHeight()
DetailPageComposable(book = it) ) {
val book by booksViewModel.getBookDetail(bookId).observeAsState()
book?.let {
DetailPageComposable(book = it)
}
} }
} }
@ -57,6 +63,7 @@ fun DetailPageComposable(book: BookUio) {
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.background(MaterialTheme.colors.background)
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
) { ) {
Image( Image(

View file

@ -3,7 +3,6 @@ package com.pixelized.biblib.ui.composable.screen
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.util.Log
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.expandVertically import androidx.compose.animation.expandVertically
@ -228,7 +227,7 @@ private fun ColumnScope.Title() {
.padding(vertical = 16.dp) .padding(vertical = 16.dp)
.align(alignment = Alignment.CenterHorizontally), .align(alignment = Alignment.CenterHorizontally),
style = typography.h4, style = typography.h4,
text = stringResource(id = R.string.welcome_sign_in) text = stringResource(id = R.string.authentication_title)
) )
} }

View file

@ -1,6 +1,8 @@
package com.pixelized.biblib.ui.composable.screen package com.pixelized.biblib.ui.composable.screen
import androidx.compose.animation.* import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.sharp.ArrowBack import androidx.compose.material.icons.sharp.ArrowBack
@ -13,6 +15,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.pixelized.biblib.R import com.pixelized.biblib.R
import com.pixelized.biblib.ui.composable.pages.DetailPageComposable import com.pixelized.biblib.ui.composable.pages.DetailPageComposable
import com.pixelized.biblib.ui.composable.pages.HomePageComposable import com.pixelized.biblib.ui.composable.pages.HomePageComposable
import com.pixelized.biblib.ui.theme.Animation
import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.ui.viewmodel.book.BooksViewModel import com.pixelized.biblib.ui.viewmodel.book.BooksViewModel
import com.pixelized.biblib.ui.viewmodel.book.IBooksViewModel import com.pixelized.biblib.ui.viewmodel.book.IBooksViewModel
@ -65,16 +68,28 @@ fun MainScreenComposable(
AnimatedVisibility( AnimatedVisibility(
visible = page is Page.HomePage, visible = page is Page.HomePage,
initiallyVisible = true, initiallyVisible = true,
enter = slideInHorizontally(initialOffsetX = { width -> -width }), enter = slideInHorizontally(
exit = slideOutHorizontally(targetOffsetX = { width -> -width }), animationSpec = tween(Animation.MEDIUM_DURATION),
initialOffsetX = { width -> -width }
),
exit = slideOutHorizontally(
animationSpec = tween(Animation.MEDIUM_DURATION),
targetOffsetX = { width -> -width }
),
) { ) {
HomePageComposable(navigationViewModel, booksViewModel) HomePageComposable(navigationViewModel, booksViewModel)
} }
AnimatedVisibility( AnimatedVisibility(
visible = page is Page.Detail, visible = page is Page.Detail,
initiallyVisible = false, initiallyVisible = false,
enter = slideInHorizontally(initialOffsetX = { width -> width }), enter = slideInHorizontally(
exit = slideOutHorizontally(targetOffsetX = { width -> width }), animationSpec = tween(Animation.MEDIUM_DURATION),
initialOffsetX = { width -> width },
),
exit = slideOutHorizontally(
animationSpec = tween(Animation.MEDIUM_DURATION),
targetOffsetX = { width -> width },
),
) { ) {
// Small trick to display the detail page during animation exit. // Small trick to display the detail page during animation exit.
var currentPage by remember { mutableStateOf<Page.Detail?>(null) } var currentPage by remember { mutableStateOf<Page.Detail?>(null) }

View file

@ -18,6 +18,7 @@ import com.pixelized.biblib.BuildConfig
import com.pixelized.biblib.R import com.pixelized.biblib.R
import com.pixelized.biblib.ui.composable.items.dialog.CrossFadeOverlay import com.pixelized.biblib.ui.composable.items.dialog.CrossFadeOverlay
import com.pixelized.biblib.ui.composable.items.dialog.ErrorCard import com.pixelized.biblib.ui.composable.items.dialog.ErrorCard
import com.pixelized.biblib.ui.theme.Animation
import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.ui.viewmodel.authentication.AuthenticationViewModel import com.pixelized.biblib.ui.viewmodel.authentication.AuthenticationViewModel
import com.pixelized.biblib.ui.viewmodel.authentication.IAuthenticationViewModel import com.pixelized.biblib.ui.viewmodel.authentication.IAuthenticationViewModel
@ -29,7 +30,6 @@ import com.pixelized.biblib.ui.viewmodel.navigation.NavigationViewModel
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import java.util.* import java.util.*
private const val ANIMATION_DURATION = 1000
private const val LAUNCH_EFFECT_AUTHENTICATION = "LAUNCH_EFFECT_AUTHENTICATION" private const val LAUNCH_EFFECT_AUTHENTICATION = "LAUNCH_EFFECT_AUTHENTICATION"
private const val LAUNCH_EFFECT_BOOK = "LAUNCH_EFFECT_BOOK" private const val LAUNCH_EFFECT_BOOK = "LAUNCH_EFFECT_BOOK"
private const val LAUNCH_EFFECT_NAVIGATION = "LAUNCH_EFFECT_NAVIGATION" private const val LAUNCH_EFFECT_NAVIGATION = "LAUNCH_EFFECT_NAVIGATION"
@ -60,7 +60,7 @@ fun SplashScreenComposable(
) { ) {
val authenticationState: IAuthenticationViewModel.State? by authenticationViewModel.state.observeAsState() val authenticationState: IAuthenticationViewModel.State? by authenticationViewModel.state.observeAsState()
val bookState by bookViewModel.state.observeAsState() val bookState by bookViewModel.state.observeAsState()
val contentVisible = remember { mutableStateOf(true) } val contentVisible = remember { mutableStateOf(false) }
// Content // Content
ContentComposable( ContentComposable(
@ -73,7 +73,10 @@ fun SplashScreenComposable(
BookError(state = bookState as? IBooksViewModel.State.Error) BookError(state = bookState as? IBooksViewModel.State.Error)
LaunchedEffect(LAUNCH_EFFECT_AUTHENTICATION) { LaunchedEffect(LAUNCH_EFFECT_AUTHENTICATION) {
delay(1500) delay(Animation.SHORT_DURATION.toLong())
contentVisible.value = true
delay(Animation.LONG_DURATION.toLong())
delay(Animation.SHORT_DURATION.toLong())
authenticationViewModel.autoLogin() authenticationViewModel.autoLogin()
} }
@ -85,14 +88,14 @@ fun SplashScreenComposable(
(bookState as? IBooksViewModel.State.Finished)?.let { (bookState as? IBooksViewModel.State.Finished)?.let {
LaunchedEffect(LAUNCH_EFFECT_NAVIGATION) { LaunchedEffect(LAUNCH_EFFECT_NAVIGATION) {
contentVisible.value = false contentVisible.value = false
delay(1000) delay(Animation.LONG_DURATION.toLong())
navigationViewModel.navigateTo(Screen.MainScreen) navigationViewModel.navigateTo(Screen.MainScreen)
} }
} }
} else { } else {
LaunchedEffect(LAUNCH_EFFECT_NAVIGATION) { LaunchedEffect(LAUNCH_EFFECT_NAVIGATION) {
contentVisible.value = false contentVisible.value = false
delay(1000) delay(Animation.LONG_DURATION.toLong())
navigationViewModel.navigateTo(Screen.LoginScreen) navigationViewModel.navigateTo(Screen.LoginScreen)
} }
} }
@ -102,7 +105,7 @@ fun SplashScreenComposable(
@OptIn(ExperimentalAnimationApi::class) @OptIn(ExperimentalAnimationApi::class)
@Composable @Composable
private fun ContentComposable( private fun ContentComposable(
duration: Int = ANIMATION_DURATION, duration: Int = Animation.LONG_DURATION,
visible: Boolean = false, visible: Boolean = false,
initiallyVisible: Boolean = false, initiallyVisible: Boolean = false,
) { ) {
@ -135,7 +138,7 @@ private fun ContentComposable(
) { ) {
Text( Text(
style = typography.h4, style = typography.h4,
text = "Welcome to" text = stringResource(id = R.string.splash_welcome)
) )
} }
AnimatedVisibility( AnimatedVisibility(

View file

@ -0,0 +1,8 @@
package com.pixelized.biblib.ui.theme
object Animation {
const val SHORT_DURATION = 300
const val MEDIUM_DURATION = 500
const val LONG_DURATION = 1000
}

View file

@ -35,7 +35,7 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
.asPagingSourceFactory(Dispatchers.Default) .asPagingSourceFactory(Dispatchers.Default)
override val books: Flow<PagingData<BookThumbnailUio>> = Pager( override val books: Flow<PagingData<BookThumbnailUio>> = Pager(
config = PagingConfig(pageSize = 20), config = PagingConfig(pageSize = PAGING_SIZE),
pagingSourceFactory = source pagingSourceFactory = source
).flow ).flow
@ -104,4 +104,8 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
series = series?.name, series = series?.name,
description = synopsis ?: "", description = synopsis ?: "",
) )
companion object {
private const val PAGING_SIZE = 30
}
} }

View file

@ -2,6 +2,8 @@
<string name="app_name">BibLib</string> <string name="app_name">BibLib</string>
<string name="app_version">%1$s: %2$s - %3$d</string> <string name="app_version">%1$s: %2$s - %3$d</string>
<!-- Actions -->
<string name="action_register">Register</string> <string name="action_register">Register</string>
<string name="action_login">Login</string> <string name="action_login">Login</string>
<string name="action_epub">EPUB</string> <string name="action_epub">EPUB</string>
@ -9,6 +11,8 @@
<string name="action_send">SEND</string> <string name="action_send">SEND</string>
<string name="action_google_sign_in">Sign in with Google</string> <string name="action_google_sign_in">Sign in with Google</string>
<!-- Dialogs -->
<string name="error_generic">Oops!</string> <string name="error_generic">Oops!</string>
<string name="error_authentication">Oops, connection failed!</string> <string name="error_authentication">Oops, connection failed!</string>
<string name="error_book">Oops! library download failed!</string> <string name="error_book">Oops! library download failed!</string>
@ -19,8 +23,11 @@
<string name="success_authentication">Authentication successful</string> <string name="success_authentication">Authentication successful</string>
<string name="success_book">Library successfully loaded</string> <string name="success_book">Library successfully loaded</string>
<string name="welcome_sign_in">Sign in to BibLib</string> <!-- Screens & pages -->
<string name="splash_welcome">Welcome to</string>
<string name="authentication_title">Sign in to BibLib</string>
<string name="authentication_login">Login</string> <string name="authentication_login">Login</string>
<string name="authentication_password">Password</string> <string name="authentication_password">Password</string>
<string name="authentication_credential_remember">Remember my credential</string> <string name="authentication_credential_remember">Remember my credential</string>