Fix some animation issue
This commit is contained in:
parent
90d6c4bd65
commit
befb235b8b
7 changed files with 61 additions and 18 deletions
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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) }
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue