Updated on 2026-08-14

This commit is contained in:
Tangem 2026-07-31 12:38:56 +03:00
parent ba9e686371
commit 22318a9ab7
2 changed files with 45 additions and 6 deletions

View file

@ -4,6 +4,7 @@ import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.Spring import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring import androidx.compose.animation.core.spring
import androidx.compose.animation.expandHorizontally import androidx.compose.animation.expandHorizontally
import androidx.compose.animation.expandVertically import androidx.compose.animation.expandVertically
@ -16,9 +17,11 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.Layout
import androidx.compose.ui.layout.layoutId import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.tooling.preview.Devices import androidx.compose.ui.tooling.preview.Devices
@ -51,8 +54,10 @@ private enum class SlotId { Start, Content, Group, End }
* [TangemTopNavigation.DefaultContentPadding] (top 8, bottom 16, horizontal 16). Override a single * [TangemTopNavigation.DefaultContentPadding] (top 8, bottom 16, horizontal 16). Override a single
* edge via [com.tangem.core.ui.extensions.copy], e.g. `DefaultContentPadding.copy(top = 16.dp)`. * edge via [com.tangem.core.ui.extensions.copy], e.g. `DefaultContentPadding.copy(top = 16.dp)`.
* @param blurBackground Whether the fade behind the row should blur the content below. * @param blurBackground Whether the fade behind the row should blur the content below.
* @param fadeEnabled Whether the fade behind the row is shown. Alpha is animated on change. Defaults to true.
* @param startButton Leading slot. Typically a back button (see [TangemButton.Back]). * @param startButton Leading slot. Typically a back button (see [TangemButton.Back]).
* @param endButtonsGroup Optional pill-grouped secondary actions placed just before [endButton]. * @param endButtonsGroup Optional pill-grouped secondary actions placed just before [endButton].
* @param isEndButtonsGroupBackgroundShown Whether the pill-grouped secondary actions should have a background. Defaults to true.
* @param endButton Trailing slot. Typically, a close button (see [TangemButton.Close]). * @param endButton Trailing slot. Typically, a close button (see [TangemButton.Close]).
* @param contentColumn Center slot. Place title/subtitle children here. * @param contentColumn Center slot. Place title/subtitle children here.
*/ */
@ -64,6 +69,8 @@ fun TangemTopNavigation(
windowInsets: WindowInsets = WindowInsets.statusBars, windowInsets: WindowInsets = WindowInsets.statusBars,
contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding, contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding,
blurBackground: Boolean = true, blurBackground: Boolean = true,
fadeEnabled: Boolean = true,
isEndButtonsGroupBackgroundShown: Boolean = true,
startButton: (@Composable () -> Unit)? = null, startButton: (@Composable () -> Unit)? = null,
endButtonsGroup: (@Composable RowScope.() -> Unit)? = null, endButtonsGroup: (@Composable RowScope.() -> Unit)? = null,
endButton: (@Composable () -> Unit)? = null, endButton: (@Composable () -> Unit)? = null,
@ -79,10 +86,17 @@ fun TangemTopNavigation(
val slotExit = remember(slotSizeSpec, slotAlphaSpec) { val slotExit = remember(slotSizeSpec, slotAlphaSpec) {
fadeOut(animationSpec = slotAlphaSpec) + shrinkHorizontally(animationSpec = slotSizeSpec) fadeOut(animationSpec = slotAlphaSpec) + shrinkHorizontally(animationSpec = slotSizeSpec)
} }
val fadeAlpha by animateFloatAsState(
targetValue = if (fadeEnabled) 1f else 0f,
animationSpec = slotAlphaSpec,
label = "TangemTopNavigation.fadeAlpha",
)
Box(modifier) { Box(modifier) {
TangemFade( TangemFade(
modifier = Modifier.matchParentSize(), modifier = Modifier
.graphicsLayer { alpha = fadeAlpha }
.matchParentSize(),
position = TangemFade.Position.Top, position = TangemFade.Position.Top,
variant = TangemFade.Variant.Soft, variant = TangemFade.Variant.Soft,
blur = blurBackground, blur = blurBackground,
@ -125,11 +139,24 @@ fun TangemTopNavigation(
exit = slotExit, exit = slotExit,
) { ) {
displayedGroup?.let { group -> displayedGroup?.let { group ->
TangemSurface(isMaterial = true, shape = CircleShape) { AnimatedContent(
Row( targetState = isEndButtonsGroupBackgroundShown,
horizontalArrangement = Arrangement.spacedBy(4.dp), transitionSpec = { fadeIn() togetherWith fadeOut() },
content = group, label = "TangemTopNavigation.endButtonsGroupBackground",
) ) { shown ->
if (shown) {
TangemSurface(isMaterial = true, shape = CircleShape) {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
content = group,
)
}
} else {
Row(
horizontalArrangement = Arrangement.spacedBy(4.dp),
content = group,
)
}
} }
} }
} }
@ -209,6 +236,8 @@ fun TangemTopNavigation(
windowInsets: WindowInsets = WindowInsets.statusBars, windowInsets: WindowInsets = WindowInsets.statusBars,
contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding, contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding,
blurBackground: Boolean = true, blurBackground: Boolean = true,
fadeEnabled: Boolean = true,
isEndButtonsGroupBackgroundShown: Boolean = true,
onBack: (() -> Unit)? = null, onBack: (() -> Unit)? = null,
endButtonsGroup: (@Composable RowScope.() -> Unit)? = null, endButtonsGroup: (@Composable RowScope.() -> Unit)? = null,
onClose: (() -> Unit)? = null, onClose: (() -> Unit)? = null,
@ -219,6 +248,8 @@ fun TangemTopNavigation(
windowInsets = windowInsets, windowInsets = windowInsets,
contentPadding = contentPadding, contentPadding = contentPadding,
blurBackground = blurBackground, blurBackground = blurBackground,
fadeEnabled = fadeEnabled,
isEndButtonsGroupBackgroundShown = isEndButtonsGroupBackgroundShown,
startButton = onBack?.let { { TangemButton.Back(onClick = it) } }, startButton = onBack?.let { { TangemButton.Back(onClick = it) } },
endButtonsGroup = endButtonsGroup, endButtonsGroup = endButtonsGroup,
endButton = onClose?.let { { TangemButton.Close(onClick = it) } }, endButton = onClose?.let { { TangemButton.Close(onClick = it) } },
@ -236,6 +267,8 @@ fun TangemTopNavigation(
windowInsets: WindowInsets = WindowInsets.statusBars, windowInsets: WindowInsets = WindowInsets.statusBars,
contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding, contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding,
blurBackground: Boolean = true, blurBackground: Boolean = true,
fadeEnabled: Boolean = true,
isEndButtonsGroupBackgroundShown: Boolean = true,
endButtonsGroup: (@Composable RowScope.() -> Unit)? = null, endButtonsGroup: (@Composable RowScope.() -> Unit)? = null,
onClose: (() -> Unit)? = null, onClose: (() -> Unit)? = null,
startButton: @Composable () -> Unit, startButton: @Composable () -> Unit,
@ -246,6 +279,8 @@ fun TangemTopNavigation(
windowInsets = windowInsets, windowInsets = windowInsets,
contentPadding = contentPadding, contentPadding = contentPadding,
blurBackground = blurBackground, blurBackground = blurBackground,
fadeEnabled = fadeEnabled,
isEndButtonsGroupBackgroundShown = isEndButtonsGroupBackgroundShown,
startButton = startButton, startButton = startButton,
endButtonsGroup = endButtonsGroup, endButtonsGroup = endButtonsGroup,
endButton = onClose?.let { { TangemButton.Close(onClick = it) } }, endButton = onClose?.let { { TangemButton.Close(onClick = it) } },
@ -263,6 +298,7 @@ fun TangemTopNavigation(
windowInsets: WindowInsets = WindowInsets.statusBars, windowInsets: WindowInsets = WindowInsets.statusBars,
contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding, contentPadding: PaddingValues = TangemTopNavigation.DefaultContentPadding,
blurBackground: Boolean = true, blurBackground: Boolean = true,
fadeEnabled: Boolean = true,
onBack: (() -> Unit)? = null, onBack: (() -> Unit)? = null,
endButton: @Composable () -> Unit, endButton: @Composable () -> Unit,
) { ) {
@ -272,6 +308,7 @@ fun TangemTopNavigation(
windowInsets = windowInsets, windowInsets = windowInsets,
contentPadding = contentPadding, contentPadding = contentPadding,
blurBackground = blurBackground, blurBackground = blurBackground,
fadeEnabled = fadeEnabled,
startButton = onBack?.let { { TangemButton.Back(onClick = it) } }, startButton = onBack?.let { { TangemButton.Back(onClick = it) } },
endButton = endButton, endButton = endButton,
contentColumn = { TitleSubtitle(title = title, subtitle = subtitle) }, contentColumn = { TitleSubtitle(title = title, subtitle = subtitle) },

View file

@ -93,6 +93,8 @@ internal fun WalletTopBar(
} else { } else {
null null
}, },
isEndButtonsGroupBackgroundShown = isWrappedBalanceShown,
fadeEnabled = isWrappedBalanceShown,
contentColumn = { contentColumn = {
AnimatedVisibility(visible = wrappedBalance != null) { AnimatedVisibility(visible = wrappedBalance != null) {
wrappedBalance?.let { balance -> wrappedBalance?.let { balance ->