Updated on 2026-08-14

This commit is contained in:
Tangem 2022-06-08 16:12:43 +03:00
parent 0df972955a
commit 4356cce18a
11 changed files with 109 additions and 103 deletions

View file

@ -1,4 +1,4 @@
package com.tangem.tap.features.home.compose.views
package com.tangem.tap.common.compose
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text

View file

@ -1,10 +1,13 @@
package com.tangem.tap.features.home.compose.uiTools
package com.tangem.tap.common.compose.extensions
import androidx.compose.animation.core.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
/**
[REDACTED_AUTHOR]
*/
typealias AnimatedValue = Pair<Float, Float>
@Composable
@ -24,8 +27,8 @@ fun AnimatedValue.toAnimatable(
@Composable
fun animatable(
values: AnimatedValue,
isPaused: Boolean,
duration: Int,
isPaused: Boolean = false,
easing: Easing = LinearEasing,
): Animatable<Float, AnimationVector1D> {
val animatable = remember { Animatable(values.first) }

View file

@ -3,6 +3,7 @@ package com.tangem.tap.common.compose.extensions
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
/**
[REDACTED_AUTHOR]
@ -11,4 +12,8 @@ import androidx.compose.ui.unit.Dp
fun Dp.toPx(): Float {
val currentDp = this
return with(LocalDensity.current) { currentDp.toPx() }
}
}
fun DpSize.halfWidth(): Dp = this.width / 2
fun DpSize.halfHeight(): Dp = this.height / 2

View file

@ -0,0 +1,19 @@
package com.tangem.tap.common.compose.extensions
import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.core.graphics.drawable.toBitmap
/**
[REDACTED_AUTHOR]
*/
@Composable
fun asImageBitmap(@DrawableRes drawableId: Int): ImageBitmap {
val drawable = AppCompatResources.getDrawable(LocalContext.current, drawableId)
?: throw NullPointerException()
return drawable.toBitmap().asImageBitmap()
}

View file

@ -0,0 +1,24 @@
package com.tangem.tap.common.compose.extensions
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.tangem.tangem_sdk_new.extensions.dpToPx
import com.tangem.tangem_sdk_new.extensions.pxToDp
/**
[REDACTED_AUTHOR]
*/
@Composable
fun Painter.dpSize(): DpSize = DpSize(
intrinsicSize.width.pxToDp().dp,
intrinsicSize.height.pxToDp().dp,
)
@Composable
private fun Float.dpToPx(): Float = LocalContext.current.dpToPx(this)
@Composable
private fun Float.pxToDp(): Float = LocalContext.current.pxToDp(this)

View file

@ -1,11 +1,8 @@
package com.tangem.tap.features.home.compose.uiTools
package com.tangem.tap.features.home.compose
import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.compose.animation.core.*
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.absoluteOffset
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.requiredHeight
import androidx.compose.foundation.layout.requiredWidth
import androidx.compose.runtime.Composable
@ -16,16 +13,14 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.core.graphics.drawable.toBitmap
import com.tangem.tap.common.compose.extensions.AnimatedValue
import com.tangem.tap.common.compose.extensions.toAnimatable
@Composable
fun HorizontalSlidingImage(
@ -37,32 +32,20 @@ fun HorizontalSlidingImage(
targetOffset: Float,
contentDescription: String,
) {
val offsetX = remember { Animatable(startOffset * -1f) }
val translateX = AnimatedValue(startOffset * -1f, (startOffset + targetOffset) * -1f)
Image(
modifier = Modifier
.offset { IntOffset(offsetX.value.toInt(), 0) }
.requiredWidth(itemSize.width)
.requiredHeight(itemSize.height),
.requiredHeight(itemSize.height)
.graphicsLayer(
translationX = translateX.toAnimatable(isPaused = paused, duration = duration).value
),
alignment = Alignment.TopStart,
contentScale = ContentScale.FillBounds,
painter = painter,
contentDescription = contentDescription,
)
LaunchedEffect(paused) {
if (paused) {
offsetX.stop()
} else {
offsetX.animateTo(
targetValue = (startOffset + targetOffset) * -1f,
animationSpec = tween(
durationMillis = duration,
easing = LinearEasing,
),
)
}
}
}
@Composable
@ -109,7 +92,7 @@ fun StoriesTextAnimation(
@Composable
fun StoriesBottomImageAnimation(
initialScale: Float = 2f,
initialScale: Float = 2.5f,
firstStepDuration: Int,
totalDuration: Int,
content: @Composable (Modifier) -> Unit
@ -120,18 +103,10 @@ fun StoriesBottomImageAnimation(
val isFirstStepLaunched = remember { mutableStateOf(false) }
val isSecondStepLaunched = remember { mutableStateOf(false) }
val firstTransition = updateTransition(targetState = isFirstStepLaunched.value, label = "Bottom image animation")
val secondTransition = updateTransition(targetState = isSecondStepLaunched.value, label = "Bottom image animation")
val fadeIn = firstTransition.animateFloat(
transitionSpec = {
tween(
durationMillis = 400,
)
},
label = "Fade in animation"
) { value -> if (value) 1f else 0f }
val firstTransition = updateTransition(
targetState = isFirstStepLaunched.value,
label = "Image appearing"
)
val firstScaleStep = firstTransition.animateFloat(
transitionSpec = {
tween(
@ -139,10 +114,13 @@ fun StoriesBottomImageAnimation(
easing = FastOutLinearInEasing,
)
},
label = "Scale"
label = "Appearing scale"
) { value -> if (value) scaleSwitchBarrier else initialScale }
val secondTransition = updateTransition(
targetState = isSecondStepLaunched.value,
label = "Image slow outgoing"
)
val secondScaleStep = secondTransition.animateFloat(
transitionSpec = {
tween(
@ -150,10 +128,17 @@ fun StoriesBottomImageAnimation(
easing = LinearEasing,
)
},
label = "Scale"
label = "Outgoing scale"
) { value -> if (value) 1f else scaleSwitchBarrier }
if (firstScaleStep.value == scaleSwitchBarrier) isSecondStepLaunched.value = true
val fadeIn = firstTransition.animateFloat(
transitionSpec = { tween(durationMillis = 400) },
label = "Fade in on start"
) { value -> if (value) 1f else 0f }
if (firstScaleStep.value == scaleSwitchBarrier) {
isSecondStepLaunched.value = true
}
val modifier = if (!isSecondStepLaunched.value) {
Modifier.scale(firstScaleStep.value)
@ -164,11 +149,4 @@ fun StoriesBottomImageAnimation(
content(modifier)
LaunchedEffect(Unit) { isFirstStepLaunched.value = true }
}
@Composable
fun asImageBitmap(@DrawableRes drawableId: Int): ImageBitmap {
val drawable = AppCompatResources.getDrawable(LocalContext.current, drawableId)
?: throw NullPointerException()
return drawable.toBitmap().asImageBitmap()
}
}

View file

@ -1,8 +1,7 @@
package com.tangem.tap.features.home.compose.uiTools
package com.tangem.tap.features.home.compose
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.tap.features.home.compose.StoriesScreen
import com.tangem.tap.features.home.compose.content.*
/**

View file

@ -26,8 +26,8 @@ import com.tangem.tangem_sdk_new.extensions.dpToPx
import com.tangem.tap.common.compose.SpacerH
import com.tangem.tap.common.compose.SpacerH16
import com.tangem.tap.common.compose.extensions.toAndroidGraphicsColor
import com.tangem.tap.features.home.compose.uiTools.StoriesBottomImageAnimation
import com.tangem.tap.features.home.compose.uiTools.StoriesTextAnimation
import com.tangem.tap.features.home.compose.StoriesBottomImageAnimation
import com.tangem.tap.features.home.compose.StoriesTextAnimation
import com.tangem.wallet.R
@Composable
@ -237,7 +237,7 @@ private fun HtmlText(
}
@Composable
fun StoriesImage(
private fun StoriesImage(
modifier: Modifier = Modifier,
@DrawableRes drawableResId: Int,
isDarkBackground: Boolean,

View file

@ -11,19 +11,17 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.tangem.tangem_sdk_new.extensions.dpToPx
import com.tangem.tangem_sdk_new.extensions.pxToDp
import com.tangem.tap.common.compose.SpacerH
import com.tangem.tap.common.compose.extensions.dpSize
import com.tangem.tap.common.compose.extensions.halfHeight
import com.tangem.tap.common.compose.extensions.toPx
import com.tangem.tap.common.extensions.isEven
import com.tangem.tap.features.home.compose.uiTools.HorizontalSlidingImage
import com.tangem.tap.features.home.compose.HorizontalSlidingImage
import com.tangem.wallet.R
@Composable
@ -89,7 +87,7 @@ fun StoriesWeb3Content(
}
val screenWidth = LocalConfiguration.current.screenWidthDp.dp
val decreaseRate = remember { 1f / dappsItemList.size }
val designItemHeight = 50.dp
val designItemHeight = 75.dp
LightenBox {
Column(modifier = Modifier.graphicsLayer(clip = false)) {
@ -101,7 +99,7 @@ fun StoriesWeb3Content(
val chessOffset = if (index.isEven()) 0.dp else scaledItemSize.width / 3
val animateFrom = chessOffset - moveItemToStartOfScreen
val animateTo = 90.dp - (90.dp * index * decreaseRate)
val animateTo = 70.dp - (70.dp * index * decreaseRate)
HorizontalSlidingImage(
paused = paused,
@ -112,7 +110,6 @@ fun StoriesWeb3Content(
targetOffset = animateTo.toPx(),
contentDescription = "Web3 row",
)
SpacerH(14.dp)
}
}
@ -126,11 +123,13 @@ private fun LightenBox(content: @Composable () -> Unit) {
Box(
modifier = Modifier
.fillMaxSize()
.padding(top = 170.dp)
.padding(top = 250.dp)
.background(
brush = Brush.verticalGradient(
colors = listOf(
Color.White.copy(alpha = 0.3f),
Color.White.copy(alpha = 0f),
Color.White.copy(alpha = 0.75f),
Color.White.copy(alpha = 0.95f),
Color.White
)
)
@ -139,23 +138,7 @@ private fun LightenBox(content: @Composable () -> Unit) {
}
}
@Composable
private fun Painter.dpSize(): DpSize = DpSize(
intrinsicSize.width.pxToDp().dp,
intrinsicSize.height.pxToDp().dp,
)
@Composable
private fun Float.dpToPx(): Float = LocalContext.current.dpToPx(this)
@Composable
private fun Float.pxToDp(): Float = LocalContext.current.pxToDp(this)
private fun scaleToDesignSize(itemSize: DpSize, designItemHeight: Dp): DpSize {
val scaleRate = itemSize.height / designItemHeight
return itemSize / scaleRate
}
private fun DpSize.halfWidth(): Dp = this.width / 2
private fun DpSize.halfHeight(): Dp = this.height / 2
}

View file

@ -19,10 +19,10 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.tangem.tap.features.home.compose.uiTools.StoriesBottomImageAnimation
import com.tangem.tap.features.home.compose.uiTools.StoriesTextAnimation
import com.tangem.tap.features.home.compose.views.FontSizeRange
import com.tangem.tap.features.home.compose.views.TextAutoSize
import com.tangem.tap.common.compose.FontSizeRange
import com.tangem.tap.common.compose.TextAutoSize
import com.tangem.tap.features.home.compose.StoriesBottomImageAnimation
import com.tangem.tap.features.home.compose.StoriesTextAnimation
import com.tangem.wallet.R
@Composable
@ -113,7 +113,7 @@ fun FirstStoriesContent(
) {
StoriesBottomImageAnimation(
totalDuration = duration,
firstStepDuration = 500,
firstStepDuration = 400,
) { modifier ->
Image(
modifier = modifier.fillMaxWidth(),
@ -128,7 +128,7 @@ fun FirstStoriesContent(
}
}
enum class StartingScreenState {
private enum class StartingScreenState {
INIT, BUY, STORE, SEND, PAY, EXCHANGE, BORROW, LEND, SHOW_CARD, MEET_TANGEM
}
@ -151,11 +151,6 @@ private fun MutableState<StartingScreenState>.isSplashingTextDisplaying(): Boole
this.value != StartingScreenState.SHOW_CARD
}
private fun MutableState<StartingScreenState>.isTangemCardDisplaying(): Boolean {
return this.value == StartingScreenState.SHOW_CARD ||
this.value == StartingScreenState.MEET_TANGEM
}
private fun MutableState<StartingScreenState>.isMeetTangemDisplaying(): Boolean {
return this.value == StartingScreenState.MEET_TANGEM
}

View file

@ -6,9 +6,9 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.graphicsLayer
import com.tangem.tap.features.home.compose.uiTools.AnimatedValue
import com.tangem.tap.features.home.compose.uiTools.asImageBitmap
import com.tangem.tap.features.home.compose.uiTools.toAnimatable
import com.tangem.tap.common.compose.extensions.AnimatedValue
import com.tangem.tap.common.compose.extensions.asImageBitmap
import com.tangem.tap.common.compose.extensions.toAnimatable
import com.tangem.wallet.R
/**
@ -84,7 +84,7 @@ private class FloatingCard {
fun second(): CardValues = CardValues(
translateX = 350f to 300f,
translateY = 0f to 50f,
translateY = -70f to 0f,
rotationX = 30f to 48f,
rotationY = 0f to 5f,
rotationZ = -34f to -42f,
@ -97,7 +97,7 @@ private class FloatingCard {
rotationX = 0f to 3f,
rotationY = 10f to 10f,
rotationZ = -45f to -30f,
scale = 0.6f to 0.7f,
scale = 0.6f to 0.75f,
)
}
}