Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-03 16:51:04 +04:00
commit 00ddaf9b12
4 changed files with 114 additions and 15 deletions

View file

@ -0,0 +1,89 @@
package com.tangem.core.ui.components
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.systemBars
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.res.TangemTheme
@Composable
fun Modifier.edgeFade(
vararg positions: FadePosition,
size: Dp,
isVisible: Boolean = true,
animationSpec: AnimationSpec<Dp>? = null,
color: Color = TangemTheme.colors.background.secondary,
): Modifier = composed {
require(value = size > 0.dp) {
"Size must be greater than '0'"
}
val animatedSize = animationSpec?.let {
animateDpAsState(
targetValue = if (isVisible) size else 0.dp,
animationSpec = it,
label = "Edge fade width",
)
}
drawWithContent {
drawContent()
positions.forEach { side ->
val (start, end) = this.size.getFadeOffsets(side)
val staticSizePx = if (isVisible) size.toPx() else 0f
val sizePx = animatedSize?.value?.toPx() ?: staticSizePx
val fraction = when (side) {
FadePosition.LEFT, FadePosition.RIGHT -> sizePx / this.size.width
FadePosition.BOTTOM, FadePosition.TOP -> sizePx / this.size.height
}
drawRect(
brush = Brush.linearGradient(
0f to color,
fraction to Color.Transparent,
start = start,
end = end,
),
size = this.size,
)
}
}
}
@Composable
fun Modifier.bottomFade(
height: Dp = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() } + 96.dp,
color: Color = TangemTheme.colors.background.secondary,
): Modifier = edgeFade(
FadePosition.BOTTOM,
size = height,
color = color,
)
enum class FadePosition {
TOP, BOTTOM, LEFT, RIGHT;
}
@Stable
private fun Size.getFadeOffsets(position: FadePosition): Pair<Offset, Offset> {
return when (position) {
FadePosition.LEFT -> Offset.Zero to Offset(width, 0f)
FadePosition.RIGHT -> Offset(width, y = 0f) to Offset.Zero
FadePosition.BOTTOM -> Offset(x = 0f, height) to Offset.Zero
FadePosition.TOP -> Offset.Zero to Offset(x = 0f, height)
}
}

View file

@ -55,8 +55,8 @@ internal class PreviewCustomTokenSelectorComponent(
network = Network(
id = n.id,
backendId = n.id.value,
name = "",
currencySymbol = "",
name = "Network $index",
currencySymbol = "N$index",
derivationPath = Network.DerivationPath.Card(""),
isTestnet = false,
standardType = Network.StandardType.ERC20,

View file

@ -20,9 +20,11 @@ import androidx.compose.ui.res.stringResource
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.util.fastForEach
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.block.information.InformationBlock
import com.tangem.core.ui.components.bottomFade
import com.tangem.core.ui.components.fields.SimpleTextField
import com.tangem.core.ui.components.isOpened
import com.tangem.core.ui.components.keyboardAsState
@ -60,18 +62,24 @@ internal fun CustomTokenFormContent(model: CustomTokenFormUM, modifier: Modifier
.fillMaxSize()
.background(color = TangemTheme.colors.background.secondary),
) {
val scrollState = rememberScrollState()
Column(
Box(
modifier = Modifier
.verticalScroll(scrollState)
.fillMaxSize()
.padding(bottom = TangemTheme.dimens.spacing76),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
.bottomFade(),
) {
AddCustomTokenDescription()
FormContent(model)
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.verticalScroll(scrollState)
.fillMaxSize()
.padding(bottom = 128.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing16),
) {
AddCustomTokenDescription()
FormContent(model)
}
}
PrimaryButton(

View file

@ -21,7 +21,9 @@ import androidx.compose.ui.res.stringResource
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 com.tangem.core.ui.components.block.information.InformationBlock
import com.tangem.core.ui.components.bottomFade
import com.tangem.core.ui.components.currency.icon.CurrencyIconState
import com.tangem.core.ui.components.rows.ChainRow
import com.tangem.core.ui.components.rows.model.ChainRowUM
@ -46,11 +48,11 @@ internal fun CustomTokenSelectorContent(model: CustomTokenSelectorUM, modifier:
val lastIndex = model.items.lastIndex
LazyColumn(
modifier = modifier.background(
color = TangemTheme.colors.background.secondary,
),
modifier = modifier
.background(color = TangemTheme.colors.background.secondary)
.bottomFade(),
contentPadding = PaddingValues(
bottom = TangemTheme.dimens.spacing16 + bottomBarHeight,
bottom = 96.dp + bottomBarHeight,
),
) {
item {