Updated on 2026-08-14
This commit is contained in:
parent
fc5fbfca7f
commit
e8c4e3a4a7
3 changed files with 79 additions and 5 deletions
|
|
@ -6,19 +6,20 @@ import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.onGloballyPositioned
|
import androidx.compose.ui.layout.onGloballyPositioned
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import com.arkivanov.decompose.extensions.compose.stack.Children
|
import com.arkivanov.decompose.extensions.compose.stack.Children
|
||||||
import com.arkivanov.decompose.extensions.compose.stack.animation.fade
|
|
||||||
import com.arkivanov.decompose.extensions.compose.stack.animation.stackAnimation
|
|
||||||
import com.arkivanov.decompose.router.stack.ChildStack
|
import com.arkivanov.decompose.router.stack.ChildStack
|
||||||
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
import com.tangem.core.ui.components.bottomsheets.state.BottomSheetState
|
||||||
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
||||||
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
import com.tangem.core.ui.res.LocalMainBottomSheetColor
|
||||||
import com.tangem.core.ui.utils.WindowInsetsZero
|
import com.tangem.core.ui.utils.WindowInsetsZero
|
||||||
import com.tangem.features.feed.components.FeedEntryChildFactory
|
import com.tangem.features.feed.components.FeedEntryChildFactory
|
||||||
|
import com.tangem.features.feed.ui.utils.contentFeedEntryStackAnimation
|
||||||
|
import com.tangem.features.feed.ui.utils.topBarFeedEntryStackAnimation
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun EntryContent(
|
internal fun EntryContent(
|
||||||
|
|
@ -29,6 +30,8 @@ internal fun EntryContent(
|
||||||
) {
|
) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val background = LocalMainBottomSheetColor.current.value
|
val background = LocalMainBottomSheetColor.current.value
|
||||||
|
val animationContent = remember { contentFeedEntryStackAnimation() }
|
||||||
|
val animationAppBar = remember { topBarFeedEntryStackAnimation() }
|
||||||
|
|
||||||
Surface(contentColor = background) {
|
Surface(contentColor = background) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
|
|
@ -52,7 +55,7 @@ internal fun EntryContent(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stack = stackState.value,
|
stack = stackState.value,
|
||||||
animation = stackAnimation(fade()),
|
animation = animationAppBar,
|
||||||
) { child ->
|
) { child ->
|
||||||
child.instance.Title(bottomSheetState)
|
child.instance.Title(bottomSheetState)
|
||||||
}
|
}
|
||||||
|
|
@ -60,7 +63,7 @@ internal fun EntryContent(
|
||||||
content = { contentPadding ->
|
content = { contentPadding ->
|
||||||
Children(
|
Children(
|
||||||
stack = stackState.value,
|
stack = stackState.value,
|
||||||
animation = stackAnimation(fade()),
|
animation = animationContent,
|
||||||
) { child ->
|
) { child ->
|
||||||
child.instance.Content(
|
child.instance.Content(
|
||||||
modifier = Modifier.padding(contentPadding),
|
modifier = Modifier.padding(contentPadding),
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
|
||||||
private const val SHOW_MORE_KEY = "privacyPolicy"
|
private const val SHOW_MORE_KEY = "privacyPolicy"
|
||||||
private const val DELAY_FOR_FOCUS_REQUEST = 200L
|
private const val DELAY_FOR_FOCUS_REQUEST = 500L
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun TopBarWithSearch(
|
internal fun TopBarWithSearch(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.tangem.features.feed.ui.utils
|
||||||
|
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.alpha
|
||||||
|
import androidx.compose.ui.layout.layout
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.arkivanov.decompose.FaultyDecomposeApi
|
||||||
|
import com.arkivanov.decompose.extensions.compose.stack.animation.*
|
||||||
|
import com.tangem.core.ui.decompose.ComposableModularBottomSheetContentComponent
|
||||||
|
import com.tangem.core.ui.utils.toPx
|
||||||
|
import com.tangem.features.feed.components.FeedEntryChildFactory
|
||||||
|
|
||||||
|
private const val DELAY_FOR_TRANSITION = 400
|
||||||
|
|
||||||
|
@OptIn(FaultyDecomposeApi::class)
|
||||||
|
internal fun topBarFeedEntryStackAnimation(): StackAnimation<
|
||||||
|
FeedEntryChildFactory.Child,
|
||||||
|
ComposableModularBottomSheetContentComponent,
|
||||||
|
> =
|
||||||
|
stackAnimation { to, from, _ ->
|
||||||
|
val isSearchToTokenList =
|
||||||
|
(to.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
|
||||||
|
val isFromSearchTokenList =
|
||||||
|
(from.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
|
||||||
|
if (isSearchToTokenList || isFromSearchTokenList) {
|
||||||
|
fade()
|
||||||
|
} else {
|
||||||
|
slide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(FaultyDecomposeApi::class)
|
||||||
|
internal fun contentFeedEntryStackAnimation(): StackAnimation<
|
||||||
|
FeedEntryChildFactory.Child,
|
||||||
|
ComposableModularBottomSheetContentComponent,
|
||||||
|
> =
|
||||||
|
stackAnimation { to, from, _ ->
|
||||||
|
val isSearchToTokenList =
|
||||||
|
(to.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
|
||||||
|
val isFromSearchTokenList =
|
||||||
|
(from.configuration as? FeedEntryChildFactory.Child.TokenList)?.params?.shouldAlwaysShowSearchBar == true
|
||||||
|
if (isSearchToTokenList || isFromSearchTokenList) {
|
||||||
|
fadeAndSlideInt()
|
||||||
|
} else {
|
||||||
|
slide()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fadeAndSlideInt(): StackAnimator =
|
||||||
|
stackAnimator(animationSpec = tween(DELAY_FOR_TRANSITION)) { factor, _, content ->
|
||||||
|
val alpha = 1f - kotlin.math.abs(factor)
|
||||||
|
val slidePx = 32.dp.toPx()
|
||||||
|
val yOffset = when {
|
||||||
|
factor > 0 -> (slidePx * factor).toInt()
|
||||||
|
factor < 0 -> (slidePx * factor * -1).toInt()
|
||||||
|
else -> 0
|
||||||
|
}
|
||||||
|
content(
|
||||||
|
Modifier
|
||||||
|
.alpha(alpha)
|
||||||
|
.offsetY(yOffset),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Modifier.offsetY(pixels: Int): Modifier = layout { measurable, constraints ->
|
||||||
|
val placeable = measurable.measure(constraints)
|
||||||
|
layout(placeable.width, placeable.height) {
|
||||||
|
placeable.placeRelative(x = 0, y = pixels)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue