Update players protrait and authentication animation

This commit is contained in:
Thomas Andres Gomez 2023-07-20 11:01:23 +02:00
parent 6f31de389d
commit 416b5278ed
9 changed files with 55 additions and 68 deletions

View file

@ -39,22 +39,30 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.dp
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.model.Lexicon
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.composable.stringResource
import com.pixelized.rplexicon.utilitary.extentions.lexicon
@Stable
data class DropDownFieldUio<T>(
@StringRes val label: Int,
val values: List<Pair<T, Int>>,
val value: State<Pair<T?, String>>,
val onValueChange: (T?, String) -> Unit,
val values: List<T>,
val value: State<T?>,
val valueLabel: @Composable (T) -> String,
val onValueChange: (T?) -> Unit,
) {
companion object {
fun <T> preview(@StringRes label: Int, id: T?, value: String) = DropDownFieldUio(
fun <T> preview(
@StringRes label: Int,
id: T?,
valueLabel: @Composable (T) -> String,
) = DropDownFieldUio(
label = label,
values = emptyList(),
value = mutableStateOf(id to value),
onValueChange = { _, _ -> },
value = mutableStateOf(id),
valueLabel = valueLabel,
onValueChange = { },
)
}
}
@ -70,7 +78,7 @@ fun <T> DropDownField(
ExposedDropdownMenuBox(
modifier = modifier,
expanded = expended,
onExpandedChange = { expended = !expended && field.value.value.first == null },
onExpandedChange = { expended = !expended && field.value.value == null },
) {
OutlinedTextField(
modifier = Modifier.menuAnchor(),
@ -85,13 +93,13 @@ fun <T> DropDownField(
trailingIcon = {
AnimatedContent(
modifier = Modifier.size(size = 48.dp),
targetState = field.value.value.first != null,
targetState = field.value.value != null,
transitionSpec = { fadeIn() with fadeOut() },
label = "DropDownFieldTrailingIconAnimation",
) {
when (it) {
true -> IconButton(
onClick = { field.onValueChange(null, "") },
onClick = { field.onValueChange(null) },
) {
Icon(
modifier = Modifier.size(size = 18.dp),
@ -116,7 +124,7 @@ fun <T> DropDownField(
focusedContainerColor = MaterialTheme.colorScheme.surface,
unfocusedContainerColor = MaterialTheme.colorScheme.surface,
),
value = field.value.value.second,
value = field.value.value?.let { field.valueLabel(it) } ?: "",
onValueChange = {},
)
@ -125,14 +133,13 @@ fun <T> DropDownField(
onDismissRequest = { expended = false },
) {
field.values.forEach {
val label = stringResource(id = it.second)
DropdownMenuItem(
onClick = {
expended = false
field.onValueChange(it.first, label)
field.onValueChange(it)
},
text = {
Text(text = label)
Text(text = field.valueLabel(it))
},
)
}
@ -144,7 +151,7 @@ fun <T> DropDownField(
@Preview(uiMode = UI_MODE_NIGHT_NO)
@Preview(uiMode = UI_MODE_NIGHT_YES)
private fun DropDownFieldPreview(
@PreviewParameter(DropDownFieldPreviewProvider::class) preview: Pair<String?, String>,
@PreviewParameter(DropDownFieldPreviewProvider::class) preview: Lexicon.Race?,
) {
LexiconTheme {
Surface {
@ -153,16 +160,17 @@ private fun DropDownFieldPreview(
.fillMaxWidth()
.padding(all = 8.dp),
field = DropDownFieldUio(
label = R.string.lexicon_search,
label = R.string.search_field_race,
values = emptyList(),
value = remember { mutableStateOf(preview) },
onValueChange = { _, _ -> },
valueLabel = { stringResource(id = it) },
onValueChange = { },
)
)
}
}
}
private class DropDownFieldPreviewProvider : PreviewParameterProvider<Pair<String?, String>> {
override val values: Sequence<Pair<String?, String>> = sequenceOf(null to "", "" to "preview")
private class DropDownFieldPreviewProvider : PreviewParameterProvider<Lexicon.Race?> {
override val values: Sequence<Lexicon.Race?> = sequenceOf(null, Lexicon.Race.HALF_ORC)
}

View file

@ -30,6 +30,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
@ -145,7 +146,7 @@ private fun PartyBackground(
Gyroscope {
val balance = remember {
derivedStateOf {
max(-1f, min(1f, this.gyroscope.value.roll))
max(-1f, min(1f, this.gyroscope.value.roll * 2.5f))
}
}
val colorFilter = remember {
@ -263,13 +264,13 @@ private fun PartyBackground(
}
@Composable
private fun rememberPortrait(): List<Int> = remember {
private fun rememberPortrait(): List<Int> = rememberSaveable {
listOf(
R.drawable.im_tigrane,
R.drawable.im_unathana,
R.drawable.im_brulkhai,
R.drawable.im_nelia,
R.drawable.im_leandre,
R.drawable.im_nelia,
)
}
@ -279,14 +280,14 @@ private fun animatedWeight(
amplitude: Float = E.toFloat(),
divergence: Float = 0.95f,
position: Float,
step: Float = .16f,
step: Float = .10f,
): Float {
val animatedWeight = animateFloatAsState(
targetValue = divergence * amplitude.pow(-(position - progress.value).pow(2f) / step) + (1f - divergence),
label = "AnimatedBackgroundWeight",
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = Spring.StiffnessLow,
stiffness = (Spring.StiffnessLow + Spring.StiffnessVeryLow) / 2f,
)
)
return animatedWeight.value
@ -378,6 +379,8 @@ private fun rememeberGoogleStringResource(): AnnotatedString {
private fun AuthenticationScreenContentPreview() {
LexiconTheme {
Surface {
PartyBackground()
AuthenticationScreenContent(
modifier = Modifier
.fillMaxSize()

View file

@ -2,7 +2,6 @@ package com.pixelized.rplexicon.ui.screens.search
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@ -34,7 +33,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
@ -51,6 +49,7 @@ import com.pixelized.rplexicon.ui.composable.form.TextFieldUio
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterDetail
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.composable.stringResource
import com.pixelized.rplexicon.utilitary.extentions.lexicon
@Stable
@ -81,8 +80,8 @@ fun SearchScreen(
screen.navigateToCharacterDetail(
id = item.id,
highlight = form.search.value.value.takeIf { it.isNotEmpty() },
race = form.race.value.value.first,
gender = form.gender.value.value.first,
race = form.race.value.value,
gender = form.gender.value.value,
)
},
onBack = {
@ -95,7 +94,7 @@ fun SearchScreen(
}
}
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SearchScreenContent(
modifier: Modifier = Modifier,
@ -178,21 +177,20 @@ private fun SearchScreenContent(
@Preview(uiMode = UI_MODE_NIGHT_YES)
private fun SearchScreenContentPreview() {
LexiconTheme {
val context = LocalContext.current
Surface {
SearchScreenContent(
modifier = Modifier.fillMaxSize(),
form = SearchFormUio(
search = TextFieldUio.preview(R.string.search_field_search),
gender = DropDownFieldUio.preview(
label = R.string.search_field_gender,
id = Lexicon.Gender.FEMALE,
value = context.getString(R.string.gender_female),
label = R.string.search_field_gender,
valueLabel = { stringResource(id = Lexicon.Gender.FEMALE) },
),
race = DropDownFieldUio.preview(
label = R.string.search_field_race,
id = null,
value = "",
label = R.string.search_field_race,
valueLabel = { stringResource(id = Lexicon.Race.HALF_ORC) },
),
),
items = remember {

View file

@ -10,6 +10,7 @@ import com.pixelized.rplexicon.model.Lexicon.Race
import com.pixelized.rplexicon.repository.LexiconRepository
import com.pixelized.rplexicon.ui.composable.form.DropDownFieldUio
import com.pixelized.rplexicon.ui.composable.form.TextFieldUio
import com.pixelized.rplexicon.utilitary.composable.stringResource
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@ -18,8 +19,8 @@ class SearchViewModel @Inject constructor(
repository: LexiconRepository,
) : ViewModel() {
private val _search = mutableStateOf("")
private val _gender = mutableStateOf<Pair<Gender?, String>>(null to "")
private val _race = mutableStateOf<Pair<Race?, String>>(null to "")
private val _gender = mutableStateOf<Gender?>(null)
private val _race = mutableStateOf<Race?>(null)
val form = SearchFormUio(
search = TextFieldUio(
@ -31,15 +32,17 @@ class SearchViewModel @Inject constructor(
),
gender = DropDownFieldUio(
label = R.string.search_field_gender,
values = genders(),
values = Lexicon.Gender.values().toList(),
value = _gender,
onValueChange = { id, value -> _gender.value = id to value },
valueLabel = { stringResource(id = it) },
onValueChange = { id -> _gender.value = id },
),
race = DropDownFieldUio(
label = R.string.search_field_race,
values = races(),
values = Lexicon.Race.values().toList(),
value = _race,
onValueChange = { id, value -> _race.value = id to value },
valueLabel = { stringResource(id = it) },
onValueChange = { id -> _race.value = id },
),
)
@ -47,8 +50,8 @@ class SearchViewModel @Inject constructor(
val filter = derivedStateOf {
data.filter { item ->
val gender = _gender.value.first?.let { it == item.gender }
val race = _race.value.first?.let { it == item.race }
val gender = _gender.value?.let { it == item.gender }
val race = _race.value?.let { it == item.race }
val search = _search.value.takeIf { it.isNotEmpty() }?.let {
val name = item.name.contains(_search.value, true)
val diminutive = item.diminutive?.contains(_search.value, true) == true
@ -66,8 +69,8 @@ class SearchViewModel @Inject constructor(
private fun Lexicon.toSearchUio(
search: String = _search.value,
highlightGender: Boolean = this.gender == _gender.value.first,
highlightRace: Boolean = this.race == _race.value.first,
highlightGender: Boolean = this.gender == _gender.value,
highlightRace: Boolean = this.race == _race.value,
) = SearchItemUio(
id = this.id,
name = this.name,
@ -80,29 +83,4 @@ class SearchViewModel @Inject constructor(
highlightGender = highlightGender,
highlightRace = highlightRace,
)
companion object {
private fun genders() = listOf(
Gender.MALE to R.string.gender_male,
Gender.FEMALE to R.string.gender_female,
Gender.UNDETERMINED to R.string.gender_undetermined,
)
private fun races() = listOf(
Race.ELF to R.string.race_elf,
Race.HALFLING to R.string.race_halfling,
Race.HUMAN to R.string.race_human,
Race.DWARF to R.string.race_dwarf,
Race.HALF_ELF to R.string.race_half_elf,
Race.HALF_ORC to R.string.race_half_orc,
Race.DRAGONBORN to R.string.race_dragonborn,
Race.GNOME to R.string.race_gnome,
Race.TIEFLING to R.string.race_tiefling,
Race.AARAKOCRA to R.string.race_aarakocra,
Race.GENASI to R.string.race_genasi,
Race.DEEP_GNOME to R.string.race_deep_gnome,
Race.GOLIATH to R.string.race_goliath,
Race.UNDETERMINED to R.string.race_undetermined,
)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Before After
Before After