From fb0ae34b4a7e25e3f5e0f3566da44e31ad4e2fde Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Wed, 2 Aug 2023 11:15:48 +0200 Subject: [PATCH] change questDetail layout to fix the background parallax --- .../remember/rememberLazyListOffset.kt | 44 --------- .../lexicon/detail/LexiconDetailScreen.kt | 12 +-- .../screens/quest/detail/QuestDetailScreen.kt | 94 +++++++------------ .../utilitary/extentions/ModifierEx.kt | 21 ++++- app/src/main/res/values-fr/strings.xml | 4 + app/src/main/res/values/strings.xml | 5 + 6 files changed, 63 insertions(+), 117 deletions(-) delete mode 100644 app/src/main/java/com/pixelized/rplexicon/ui/composable/remember/rememberLazyListOffset.kt diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/composable/remember/rememberLazyListOffset.kt b/app/src/main/java/com/pixelized/rplexicon/ui/composable/remember/rememberLazyListOffset.kt deleted file mode 100644 index fe3b8db..0000000 --- a/app/src/main/java/com/pixelized/rplexicon/ui/composable/remember/rememberLazyListOffset.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.pixelized.rplexicon.ui.composable.remember - -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -import androidx.compose.runtime.State -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.input.nestedscroll.NestedScrollConnection -import androidx.compose.ui.input.nestedscroll.NestedScrollSource -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -@Stable -data class LazyListOffset( - val offsetY: State, - val connection: NestedScrollConnection, -) - -@Composable -@Stable -fun rememberLazyListOffset( - lazyListState: LazyListState, -): LazyListOffset { - val density = LocalDensity.current - - return remember { - val offsetY = mutableStateOf(0.dp) - - LazyListOffset( - offsetY = offsetY, - connection = object : NestedScrollConnection { - override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { - if (lazyListState.canScrollForward || lazyListState.canScrollBackward) { - offsetY.value -= with(density) { available.y.toDp() } - } - return Offset.Zero - } - }, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt index a196673..e88aa3f 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/lexicon/detail/LexiconDetailScreen.kt @@ -62,6 +62,7 @@ import com.pixelized.rplexicon.utilitary.composable.stringResource import com.pixelized.rplexicon.utilitary.extentions.annotatedSpan import com.pixelized.rplexicon.utilitary.extentions.annotatedString import com.pixelized.rplexicon.utilitary.extentions.highlightRegex +import com.pixelized.rplexicon.utilitary.extentions.scrollOffset import com.skydoves.landscapist.ImageOptions @Stable @@ -189,7 +190,7 @@ private fun LexiconDetailContent( ) }, ) { paddingValues -> - Box( + Surface( modifier = Modifier.padding(paddingValues = paddingValues), ) { annotatedItem.portrait.firstOrNull()?.let { uri -> @@ -332,15 +333,6 @@ private fun rememberPortraitWidth(): Dp { } } -@Stable -private fun Modifier.scrollOffset( - scrollState: ScrollState, - block: (Dp) -> Dp -): Modifier = composed { - val density = LocalDensity.current - this.offset(y = with(density) { block(scrollState.value.toDp()) }) -} - @Composable @Preview(uiMode = UI_MODE_NIGHT_NO, heightDp = 980) @Preview(uiMode = UI_MODE_NIGHT_YES, heightDp = 980) diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt index 32a9212..5f0a67d 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/quest/detail/QuestDetailScreen.kt @@ -3,20 +3,18 @@ package com.pixelized.rplexicon.ui.screens.quest.detail import android.content.res.Configuration import android.net.Uri import androidx.compose.foundation.Image +import androidx.compose.foundation.ScrollState import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.offset 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.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -32,11 +30,9 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.composed import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -47,17 +43,15 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.pixelized.rplexicon.R import com.pixelized.rplexicon.ui.composable.BackgroundImage -import com.pixelized.rplexicon.ui.composable.remember.LazyListOffset -import com.pixelized.rplexicon.ui.composable.remember.rememberLazyListOffset import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost import com.pixelized.rplexicon.ui.navigation.screens.navigateToLexiconDetail import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.utilitary.extentions.lexicon +import com.pixelized.rplexicon.utilitary.extentions.scrollOffset import java.lang.Integer.min @Stable @@ -160,11 +154,11 @@ fun QuestDetailScreen( @Composable private fun QuestDetailContent( modifier: Modifier = Modifier, + state: ScrollState = rememberScrollState(), item: State, onBack: () -> Unit, onGiver: (Int) -> Unit, ) { - val state = rememberLazyListState() val annotatedQuest = item.value.annotate() Scaffold( @@ -186,51 +180,42 @@ private fun QuestDetailContent( ) }, content = { padding -> - val lazyListOffset = rememberLazyListOffset(lazyListState = state) Surface( - modifier = Modifier - .padding(padding) - .nestedScroll(lazyListOffset.connection), + modifier = Modifier.padding(padding), ) { BackgroundImage( modifier = Modifier .fillMaxWidth() .aspectRatio(ratio = 1f) - .scrollOffset(scrollState = lazyListOffset) { -it / 2 }, + .scrollOffset(scrollState = state) { -it / 2 }, model = { annotatedQuest.background }, ) - LazyColumn( - state = state, - contentPadding = PaddingValues( - top = 248.dp, - bottom = 16.dp, - start = 16.dp, - end = 16.dp - ), - verticalArrangement = Arrangement.spacedBy(0.dp), + Column( + modifier = Modifier + .verticalScroll(state) + .padding(top = 248.dp, bottom = 16.dp, start = 16.dp, end = 16.dp), ) { - item { - Column { - Text( - modifier = Modifier.fillMaxWidth(), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.displaySmall, - text = annotatedQuest.title, - ) - Image( - modifier = Modifier - .height(24.dp) - .graphicsLayer { rotationZ = 180f } - .align(Alignment.CenterHorizontally), - painter = painterResource(id = R.drawable.art_divider_1), - contentScale = ContentScale.FillWidth, - alignment = Alignment.Center, - colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface), - contentDescription = null, - ) - } + Column { + Text( + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.displaySmall, + text = annotatedQuest.title, + ) + Image( + modifier = Modifier + .height(24.dp) + .graphicsLayer { rotationZ = 180f } + .align(Alignment.CenterHorizontally), + painter = painterResource(id = R.drawable.art_divider_1), + contentScale = ContentScale.FillWidth, + alignment = Alignment.Center, + colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface), + contentDescription = null, + ) } - items(annotatedQuest.steps) { quest -> + + annotatedQuest.steps.forEach { quest -> Column( verticalArrangement = Arrangement.spacedBy(16.dp), ) { @@ -279,7 +264,7 @@ private fun QuestDetailContent( Text( style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, - text = "Commanditaire", + text = stringResource(id = R.string.quest_detail_giver), ) Text( style = MaterialTheme.typography.bodyMedium, @@ -292,7 +277,7 @@ private fun QuestDetailContent( Text( style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, - text = "Lieu", + text = stringResource(id = R.string.quest_detail_area), ) Text( style = MaterialTheme.typography.bodyMedium, @@ -305,7 +290,7 @@ private fun QuestDetailContent( Text( style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, - text = "Récompense de groupe", + text = stringResource(id = R.string.quest_detail_individual_reward), ) Text( style = MaterialTheme.typography.bodyMedium, @@ -318,7 +303,7 @@ private fun QuestDetailContent( Text( style = MaterialTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, - text = "Récompense individuelle", + text = stringResource(id = R.string.quest_detail_group_rewars), ) Text( style = MaterialTheme.typography.bodyMedium, @@ -335,19 +320,10 @@ private fun QuestDetailContent( } } } - }, ) } -@Stable -private fun Modifier.scrollOffset( - scrollState: LazyListOffset, - block: (Dp) -> Dp -): Modifier = composed { - this.offset(y = block(scrollState.offsetY.value)) -} - @Composable @Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) diff --git a/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt b/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt index c526fb5..6a06090 100644 --- a/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt +++ b/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt @@ -3,23 +3,27 @@ package com.pixelized.rplexicon.utilitary.extentions import androidx.compose.animation.core.FiniteAnimationSpec import androidx.compose.animation.core.Transition import androidx.compose.animation.core.spring +import androidx.compose.foundation.ScrollState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.google.accompanist.placeholder.PlaceholderHighlight import com.google.accompanist.placeholder.placeholder -@Composable fun Modifier.placeholder( - color: Color = MaterialTheme.lexicon.colorScheme.placeholder, + color: Color = Color.Unspecified, shape: Shape = CircleShape, highlight: PlaceholderHighlight? = null, placeholderFadeTransitionSpec: @Composable Transition.Segment.() -> FiniteAnimationSpec = { spring() }, @@ -28,7 +32,7 @@ fun Modifier.placeholder( ): Modifier = composed { placeholder( visible = visible(), - color = color, + color = if (color == Color.Unspecified) MaterialTheme.lexicon.colorScheme.placeholder else color, shape = shape, highlight = highlight, placeholderFadeTransitionSpec = placeholderFadeTransitionSpec, @@ -36,10 +40,19 @@ fun Modifier.placeholder( ) } -@Composable +@Stable fun Modifier.cell() = composed { Modifier .fillMaxWidth() .heightIn(min = MaterialTheme.lexicon.dimens.item) .padding(horizontal = 16.dp, vertical = 4.dp) +} + +@Stable +fun Modifier.scrollOffset( + scrollState: ScrollState, + block: (Dp) -> Dp +): Modifier = composed { + val density = LocalDensity.current + this.offset(y = with(density) { block(scrollState.value.toDp()) }) } \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7d3e718..f43dae7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -47,4 +47,8 @@ Mots clés : Détails de quête + Commanditaire : + Lieu : + Récompense individuelle : + Récompense de groupe : \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f13474c..9c859de 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -47,4 +47,9 @@ Tags: Quest details + Quest giver: + Area: + Individual reward: + Group reward: + \ No newline at end of file