Small UX fix.
Trim on search. keyboard action done focus. maxline on search. collapsing header on search. remove keyboard hide on search scroll.
This commit is contained in:
parent
99f7546621
commit
82738a8f03
9 changed files with 303 additions and 113 deletions
|
|
@ -0,0 +1,57 @@
|
|||
package com.pixelized.rplexicon.ui.composable
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import com.bumptech.glide.request.RequestListener
|
||||
import com.pixelized.rplexicon.utilitary.rememberLoadingTransition
|
||||
import com.skydoves.landscapist.ImageOptions
|
||||
import com.skydoves.landscapist.InternalLandscapistApi
|
||||
import com.skydoves.landscapist.components.ImageComponent
|
||||
import com.skydoves.landscapist.components.rememberImageComponent
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import com.skydoves.landscapist.glide.GlideImageState
|
||||
import com.skydoves.landscapist.glide.GlideRequestType
|
||||
|
||||
@Composable
|
||||
fun AsyncImage(
|
||||
imageModel: () -> Any?,
|
||||
modifier: Modifier = Modifier,
|
||||
glideRequestType: GlideRequestType = GlideRequestType.DRAWABLE,
|
||||
requestListener: (() -> RequestListener<Any>)? = null,
|
||||
component: ImageComponent = rememberImageComponent {},
|
||||
imageOptions: ImageOptions = ImageOptions(),
|
||||
onImageStateChanged: (GlideImageState) -> Unit = {},
|
||||
@DrawableRes previewPlaceholder: Int = 0,
|
||||
loading: @Composable (BoxScope.(imageState: GlideImageState.Loading) -> Unit)? = null,
|
||||
success: @Composable (BoxScope.(imageState: GlideImageState.Success, painter: Painter) -> Unit)? = null,
|
||||
failure: @Composable (BoxScope.(imageState: GlideImageState.Failure) -> Unit)? = null,
|
||||
) {
|
||||
val transition = rememberLoadingTransition(imageModel)
|
||||
|
||||
GlideImage(
|
||||
imageModel = imageModel,
|
||||
modifier = modifier.alpha(alpha = transition.alpha),
|
||||
glideRequestType = glideRequestType,
|
||||
requestListener = requestListener,
|
||||
component = component,
|
||||
imageOptions = imageOptions,
|
||||
onImageStateChanged = {
|
||||
when (it) {
|
||||
is GlideImageState.Success -> transition.target = 1f
|
||||
is GlideImageState.Failure -> transition.target = 1f
|
||||
is GlideImageState.Loading -> transition.target = 0f
|
||||
is GlideImageState.None -> transition.target = 0f
|
||||
}
|
||||
onImageStateChanged(it)
|
||||
},
|
||||
previewPlaceholder = previewPlaceholder,
|
||||
loading = loading,
|
||||
success = success,
|
||||
failure = failure,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,92 @@
|
|||
package com.pixelized.rplexicon.ui.composable
|
||||
|
||||
import androidx.compose.animation.core.animateIntAsState
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.layout.Layout
|
||||
import androidx.compose.ui.layout.Measurable
|
||||
import androidx.compose.ui.layout.layoutId
|
||||
import androidx.compose.ui.unit.Velocity
|
||||
|
||||
private val List<Measurable>.grid: Measurable get() = first { it.layoutId == GRID_ID }
|
||||
private val List<Measurable>.header: Measurable get() = first { it.layoutId == HEADER_ID }
|
||||
|
||||
private const val GRID_ID = "GRID_ID"
|
||||
private const val HEADER_ID = "HEADER_ID"
|
||||
|
||||
@Composable
|
||||
fun CollapsingHeader(
|
||||
modifier: Modifier = Modifier,
|
||||
header: @Composable () -> Unit,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val headerHeight = rememberSaveable { mutableStateOf(0) }
|
||||
val headerScroll = rememberSaveable { mutableStateOf(0) }
|
||||
|
||||
val animatedHeaderScroll = animateIntAsState(
|
||||
targetValue = headerScroll.value,
|
||||
label = "HeaderSnapAnimation",
|
||||
)
|
||||
|
||||
val nestedScrollConnection = remember {
|
||||
object : NestedScrollConnection {
|
||||
override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
|
||||
val scroll = (headerScroll.value + available.y.toInt()).coerceIn(
|
||||
minimumValue = -headerHeight.value,
|
||||
maximumValue = 0,
|
||||
)
|
||||
return if (headerScroll.value != scroll) {
|
||||
headerScroll.value = scroll
|
||||
available
|
||||
} else {
|
||||
Offset.Zero
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity {
|
||||
headerScroll.value = if (headerScroll.value < -headerHeight.value / 2) {
|
||||
-headerHeight.value
|
||||
} else {
|
||||
0
|
||||
}
|
||||
return super.onPostFling(consumed, available)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Layout(
|
||||
modifier = modifier.nestedScroll(nestedScrollConnection),
|
||||
content = {
|
||||
Box(
|
||||
modifier = Modifier.layoutId(HEADER_ID),
|
||||
content = { header() },
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier.layoutId(GRID_ID),
|
||||
content = { content() },
|
||||
)
|
||||
},
|
||||
measurePolicy = { measurables, constraints ->
|
||||
val headerPlaceable = measurables.header.measure(constraints)
|
||||
val gridPlaceable = measurables.grid.measure(constraints)
|
||||
|
||||
if (headerHeight.value == 0) {
|
||||
headerHeight.value = headerPlaceable.height
|
||||
}
|
||||
|
||||
layout(constraints.maxWidth, constraints.maxHeight) {
|
||||
headerPlaceable.place(0, animatedHeaderScroll.value)
|
||||
gridPlaceable.place(0, headerPlaceable.height + animatedHeaderScroll.value)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
package com.pixelized.rplexicon.ui.composable
|
||||
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
fun ScrollingKeyboardHandler(
|
||||
lazyListState: LazyListState
|
||||
) {
|
||||
val keyboard = LocalSoftwareKeyboardController.current
|
||||
|
||||
if (lazyListState.isScrollInProgress) {
|
||||
keyboard?.hide()
|
||||
}
|
||||
}
|
||||
|
|
@ -9,6 +9,8 @@ import androidx.compose.animation.fadeOut
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
|
|
@ -22,8 +24,11 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
|
|
@ -52,6 +57,8 @@ fun TextField(
|
|||
modifier: Modifier = Modifier,
|
||||
field: TextFieldUio,
|
||||
) {
|
||||
val focus = LocalFocusManager.current
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = modifier,
|
||||
shape = MaterialTheme.lexicon.shapes.textField,
|
||||
|
|
@ -77,6 +84,14 @@ fun TextField(
|
|||
}
|
||||
}
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Text,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
keyboardActions = KeyboardActions(
|
||||
onDone = { focus.clearFocus(true) },
|
||||
),
|
||||
maxLines = 1,
|
||||
value = field.value.value,
|
||||
onValueChange = field.onValueChange,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -48,6 +47,7 @@ import androidx.compose.ui.graphics.Shadow
|
|||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalView
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
|
|
@ -59,16 +59,14 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.model.Lexicon
|
||||
import com.pixelized.rplexicon.ui.composable.AsyncImage
|
||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
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.rememberLoadingTransition
|
||||
import com.skydoves.landscapist.ImageOptions
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import com.skydoves.landscapist.glide.GlideImageState
|
||||
|
||||
@Stable
|
||||
data class CharacterDetailUio(
|
||||
|
|
@ -200,16 +198,8 @@ private fun CharacterDetailScreenContent(
|
|||
.aspectRatio(ratio = 1f)
|
||||
.scrollOffset(scrollState = state) { -it / 2 },
|
||||
) {
|
||||
val transition = rememberLoadingTransition { uri }
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.alpha(alpha = transition.alpha),
|
||||
onImageStateChanged = {
|
||||
if (it is GlideImageState.Success) {
|
||||
transition.target = 1f
|
||||
}
|
||||
},
|
||||
AsyncImage(
|
||||
modifier = Modifier.matchParentSize(),
|
||||
imageOptions = ImageOptions(
|
||||
alignment = Alignment.TopCenter,
|
||||
contentScale = ContentScale.Crop,
|
||||
|
|
@ -299,8 +289,7 @@ private fun CharacterDetailScreenContent(
|
|||
)
|
||||
}
|
||||
if (annotatedItem.portrait.isNotEmpty()) {
|
||||
val configuration = LocalConfiguration.current
|
||||
val maxSize = remember { (configuration.screenWidthDp.dp - 16.dp * 2) }
|
||||
val maxSize = rememberPortraitWidth()
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 16.dp, top = 24.dp, end = 16.dp),
|
||||
style = typography.titleMedium,
|
||||
|
|
@ -308,19 +297,16 @@ private fun CharacterDetailScreenContent(
|
|||
)
|
||||
LazyRow(
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
items(items = annotatedItem.portrait) {
|
||||
val transition = rememberLoadingTransition { it }
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.sizeIn(maxWidth = maxSize, maxHeight = maxSize)
|
||||
.alpha(alpha = transition.alpha),
|
||||
onImageStateChanged = {
|
||||
if (it is GlideImageState.Success) {
|
||||
transition.target = 1f
|
||||
}
|
||||
},
|
||||
AsyncImage(
|
||||
modifier = Modifier.sizeIn(
|
||||
minWidth = maxSize / 2,
|
||||
maxWidth = maxSize,
|
||||
minHeight = maxSize,
|
||||
maxHeight = maxSize,
|
||||
),
|
||||
imageOptions = ImageOptions(
|
||||
contentScale = ContentScale.FillHeight
|
||||
),
|
||||
|
|
@ -348,6 +334,19 @@ private fun rememberBackgroundGradient(): Brush {
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun rememberPortraitWidth(): Dp {
|
||||
val configuration = LocalConfiguration.current
|
||||
val view = LocalView.current
|
||||
return remember(configuration, view) {
|
||||
if (view.isInEditMode) {
|
||||
300.dp
|
||||
} else {
|
||||
(configuration.screenWidthDp.dp - 16.dp * 2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Stable
|
||||
private fun Modifier.scrollOffset(
|
||||
scrollState: ScrollState,
|
||||
|
|
|
|||
|
|
@ -99,12 +99,13 @@ class AnnotatedSearchItemUio(
|
|||
private fun SearchItemUio.annotate(): AnnotatedSearchItemUio {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val highlight = remember { SpanStyle(color = colorScheme.primary) }
|
||||
val highlightRegex = remember(search) { search.highlightRegex }
|
||||
val finderRegex = remember(search) { search.finderRegex }
|
||||
val trimmedSearch = remember(search) { search.trim() }
|
||||
val highlightRegex = remember(search) { trimmedSearch.highlightRegex }
|
||||
val finderRegex = remember(search) { trimmedSearch.finderRegex }
|
||||
val gender = stringResource(id = gender, short = true)
|
||||
val race = stringResource(id = race)
|
||||
|
||||
return remember(search, race, highlightRace, gender, highlightGender) {
|
||||
return remember(trimmedSearch, race, highlightRace, gender, highlightGender) {
|
||||
AnnotatedSearchItemUio(
|
||||
id = id,
|
||||
name = AnnotatedString(
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import com.pixelized.rplexicon.NO_WINDOW_INSETS
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.model.Lexicon
|
||||
import com.pixelized.rplexicon.ui.composable.ScrollingKeyboardHandler
|
||||
import com.pixelized.rplexicon.ui.composable.CollapsingHeader
|
||||
import com.pixelized.rplexicon.ui.composable.form.DropDownField
|
||||
import com.pixelized.rplexicon.ui.composable.form.DropDownFieldUio
|
||||
import com.pixelized.rplexicon.ui.composable.form.TextField
|
||||
|
|
@ -88,9 +88,6 @@ fun SearchScreen(
|
|||
screen.popBackStack()
|
||||
}
|
||||
)
|
||||
ScrollingKeyboardHandler(
|
||||
lazyListState = lazyState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,50 +122,64 @@ private fun SearchScreenContent(
|
|||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues = paddingValues),
|
||||
state = lazyColumnState,
|
||||
contentPadding = PaddingValues(vertical = 8.dp),
|
||||
) {
|
||||
item {
|
||||
Column(
|
||||
CollapsingHeader(
|
||||
modifier = Modifier.padding(paddingValues = paddingValues),
|
||||
header = {
|
||||
SearchBox(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
form = form,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
state = lazyColumnState,
|
||||
contentPadding = PaddingValues(vertical = 8.dp),
|
||||
) {
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
field = form.search,
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
items(
|
||||
items = items.value,
|
||||
key = { it.id },
|
||||
contentType = { "Search" },
|
||||
) {
|
||||
DropDownField(
|
||||
modifier = Modifier.weight(1f),
|
||||
field = form.gender,
|
||||
)
|
||||
DropDownField(
|
||||
modifier = Modifier.weight(1f),
|
||||
field = form.race,
|
||||
SearchItem(
|
||||
modifier = Modifier
|
||||
.clickable { onItem(it) }
|
||||
.heightIn(min = MaterialTheme.lexicon.dimens.item),
|
||||
item = it,
|
||||
)
|
||||
}
|
||||
Divider(modifier = Modifier.padding(top = 16.dp, bottom = 8.dp))
|
||||
}
|
||||
}
|
||||
items(
|
||||
items = items.value,
|
||||
key = { it.id },
|
||||
contentType = { "Search" },
|
||||
) {
|
||||
SearchItem(
|
||||
modifier = Modifier
|
||||
.clickable { onItem(it) }
|
||||
.heightIn(min = MaterialTheme.lexicon.dimens.item),
|
||||
item = it,
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SearchBox(
|
||||
modifier: Modifier = Modifier,
|
||||
form: SearchFormUio,
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
) {
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
field = form.search,
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
) {
|
||||
DropDownField(
|
||||
modifier = Modifier.weight(1f),
|
||||
field = form.gender,
|
||||
)
|
||||
DropDownField(
|
||||
modifier = Modifier.weight(1f),
|
||||
field = form.race,
|
||||
)
|
||||
}
|
||||
Divider(modifier = Modifier.padding(top = 16.dp, bottom = 8.dp))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,18 +207,41 @@ private fun SearchScreenContentPreview() {
|
|||
items = remember {
|
||||
mutableStateOf(
|
||||
listOf(
|
||||
SearchItemUio(
|
||||
SearchItemUio.preview(
|
||||
id = 0,
|
||||
name = "Brulkhai",
|
||||
diminutive = "Bru",
|
||||
gender = Lexicon.Gender.FEMALE,
|
||||
race = Lexicon.Race.HALF_ORC,
|
||||
description = null,
|
||||
history = null,
|
||||
search = "",
|
||||
highlightGender = false,
|
||||
highlightRace = false,
|
||||
)
|
||||
),
|
||||
SearchItemUio.preview(
|
||||
id = 0,
|
||||
name = "Léandre",
|
||||
diminutive = null,
|
||||
gender = Lexicon.Gender.MALE,
|
||||
race = Lexicon.Race.HUMAN,
|
||||
),
|
||||
SearchItemUio.preview(
|
||||
id = 0,
|
||||
name = "Nélia",
|
||||
diminutive = null,
|
||||
gender = Lexicon.Gender.FEMALE,
|
||||
race = Lexicon.Race.ELF,
|
||||
),
|
||||
SearchItemUio.preview(
|
||||
id = 0,
|
||||
name = "Tigrane",
|
||||
diminutive = null,
|
||||
gender = Lexicon.Gender.MALE,
|
||||
race = Lexicon.Race.TIEFLING,
|
||||
),
|
||||
SearchItemUio.preview(
|
||||
id = 0,
|
||||
name = "Unathana",
|
||||
diminutive = "Una",
|
||||
gender = Lexicon.Gender.FEMALE,
|
||||
race = Lexicon.Race.HALF_ELF,
|
||||
),
|
||||
)
|
||||
)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -52,11 +52,11 @@ class SearchViewModel @Inject constructor(
|
|||
data.filter { item ->
|
||||
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
|
||||
val description = item.description?.contains(_search.value, true) == true
|
||||
val history = item.history?.contains(_search.value, true) == true
|
||||
val search = _search.value.takeIf { it.isNotEmpty() }?.trim()?.let { search ->
|
||||
val name = item.name.contains(search, true)
|
||||
val diminutive = item.diminutive?.contains(search, true) == true
|
||||
val description = item.description?.contains(search, true) == true
|
||||
val history = item.history?.contains(search, true) == true
|
||||
name || diminutive || description || history
|
||||
}
|
||||
(gender == null || gender) && (race == null || race) && (search == null || search)
|
||||
|
|
|
|||
|
|
@ -23,18 +23,28 @@ class GlideLoadingTransition(
|
|||
@Composable
|
||||
fun rememberLoadingTransition(model: () -> Any?): GlideLoadingTransition {
|
||||
val isInEditMode = LocalView.current.isInEditMode
|
||||
val key = model()
|
||||
val target = remember(key) {
|
||||
mutableStateOf(if (isInEditMode) 1f else 0f)
|
||||
}
|
||||
val alpha = animateFloatAsState(
|
||||
targetValue = target.value,
|
||||
label = "RememberLoadingTransition"
|
||||
)
|
||||
return remember(key) {
|
||||
GlideLoadingTransition(
|
||||
target = target,
|
||||
alpha = alpha,
|
||||
|
||||
return if (isInEditMode) {
|
||||
remember {
|
||||
GlideLoadingTransition(
|
||||
target = mutableStateOf(1f),
|
||||
alpha = mutableStateOf(1f),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
val key = model()
|
||||
val target = remember(key) {
|
||||
mutableStateOf(0f)
|
||||
}
|
||||
val alpha = animateFloatAsState(
|
||||
targetValue = target.value,
|
||||
label = "LoadingAlphaTransition"
|
||||
)
|
||||
remember(key) {
|
||||
GlideLoadingTransition(
|
||||
target = target,
|
||||
alpha = alpha,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue