Updated on 2026-08-14
This commit is contained in:
commit
d3068f5818
9 changed files with 195 additions and 48 deletions
|
|
@ -5,7 +5,10 @@ import androidx.compose.foundation.layout.*
|
|||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -15,6 +18,7 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.ui.components.progressbar.TangemLinearProgressIndicator
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
|
|
@ -71,7 +75,7 @@ private fun AddSessionFab(onAddSession: () -> Unit, modifier: Modifier = Modifie
|
|||
@Composable
|
||||
private fun EmptyScreen(state: WalletConnectScreenState) {
|
||||
if (state.isLoading) {
|
||||
LinearProgressIndicator(
|
||||
TangemLinearProgressIndicator(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
color = TangemTheme.colors.icon.accent,
|
||||
)
|
||||
|
|
@ -102,7 +106,7 @@ private fun EmptyScreen(state: WalletConnectScreenState) {
|
|||
@Composable
|
||||
private fun WalletConnectSessions(state: WalletConnectScreenState) {
|
||||
if (state.isLoading) {
|
||||
LinearProgressIndicator(
|
||||
TangemLinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(2.dp),
|
||||
|
|
|
|||
17
app/src/main/res/drawable/progress_rounded_shape.xml
Normal file
17
app/src/main/res/drawable/progress_rounded_shape.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="4dp"/>
|
||||
<solid android:color="@color/icon_informative" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item android:id="@android:id/progress">
|
||||
<scale android:scaleWidth="100%">
|
||||
<shape>
|
||||
<corners android:radius="4dp" />
|
||||
<solid android:color="@color/icon_primary_1" />
|
||||
</shape>
|
||||
</scale>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
|
@ -4,9 +4,10 @@
|
|||
android:id="@+id/pb_state"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:progressBackgroundTint="@color/icon_informative"
|
||||
android:progressTint="@color/icon_primary_1" />
|
||||
android:paddingVertical="8dp"
|
||||
android:indeterminate="false"
|
||||
android:progressDrawable="@drawable/progress_rounded_shape" />
|
||||
</merge>
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
package com.tangem.core.ui.components.progressbar
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.*
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -39,7 +39,7 @@ import kotlin.math.abs
|
|||
* @param strokeCap stroke cap to use for the ends of this progress indicator
|
||||
*/
|
||||
@Composable
|
||||
fun LinearProgressIndicator(
|
||||
fun TangemLinearProgressIndicator(
|
||||
progress: () -> Float,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = TangemTheme.colors.text.accent,
|
||||
|
|
@ -61,6 +61,99 @@ fun LinearProgressIndicator(
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Progress indicators loading status with infinite animation
|
||||
*
|
||||
* @param modifier the [Modifier] to be applied to this progress indicator
|
||||
* @param color The color of the progress indicator.
|
||||
* @param backgroundColor The color of the background behind the indicator, visible when the
|
||||
* progress has not reached that area of the overall indicator yet.
|
||||
* @param strokeCap stroke cap to use for the ends of this progress indicator
|
||||
*/
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
fun TangemLinearProgressIndicator(
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = TangemTheme.colors.text.accent,
|
||||
backgroundColor: Color = TangemTheme.colors.background.tertiary,
|
||||
strokeCap: StrokeCap = StrokeCap.Round,
|
||||
) {
|
||||
val infiniteTransition = rememberInfiniteTransition()
|
||||
val firstLineHead by infiniteTransition.animateFloat(
|
||||
0f,
|
||||
1f,
|
||||
infiniteRepeatable(
|
||||
animation = keyframes {
|
||||
durationMillis = LINEAR_ANIMATION_DURATION
|
||||
0f at FIRST_LINE_HEAD_DELAY using FIRST_LINE_HEAD_EASING
|
||||
1f at FIRST_LINE_HEAD_DURATION + FIRST_LINE_HEAD_DELAY
|
||||
},
|
||||
),
|
||||
)
|
||||
val firstLineTail by infiniteTransition.animateFloat(
|
||||
0f,
|
||||
1f,
|
||||
infiniteRepeatable(
|
||||
animation = keyframes {
|
||||
durationMillis = LINEAR_ANIMATION_DURATION
|
||||
0f at FIRST_LINE_TAIL_DELAY using FIRST_LINE_TAIL_EASING
|
||||
1f at FIRST_LINE_TAIL_DURATION + FIRST_LINE_TAIL_DELAY
|
||||
},
|
||||
),
|
||||
)
|
||||
val secondLineHead by infiniteTransition.animateFloat(
|
||||
0f,
|
||||
1f,
|
||||
infiniteRepeatable(
|
||||
animation = keyframes {
|
||||
durationMillis = LINEAR_ANIMATION_DURATION
|
||||
0f at SECOND_LINE_HEAD_DELAY using SECOND_LINE_HEAD_EASING
|
||||
1f at SECOND_LINE_HEAD_DURATION + SECOND_LINE_HEAD_DELAY
|
||||
},
|
||||
),
|
||||
)
|
||||
val secondLineTail by infiniteTransition.animateFloat(
|
||||
0f,
|
||||
1f,
|
||||
infiniteRepeatable(
|
||||
animation = keyframes {
|
||||
durationMillis = LINEAR_ANIMATION_DURATION
|
||||
0f at SECOND_LINE_TAIL_DELAY using SECOND_LINE_TAIL_EASING
|
||||
1f at SECOND_LINE_TAIL_DURATION + SECOND_LINE_TAIL_DELAY
|
||||
},
|
||||
),
|
||||
)
|
||||
Canvas(
|
||||
modifier
|
||||
.increaseSemanticsBounds()
|
||||
.semantics(mergeDescendants = true) {
|
||||
progressBarRangeInfo = ProgressBarRangeInfo.Indeterminate
|
||||
}
|
||||
.size(height = 4.dp, width = 24.dp),
|
||||
) {
|
||||
val strokeWidth = size.height
|
||||
drawLinearIndicatorBackground(backgroundColor, strokeWidth, strokeCap)
|
||||
if (firstLineHead - firstLineTail > 0) {
|
||||
drawLinearIndicator(
|
||||
firstLineHead,
|
||||
firstLineTail,
|
||||
color,
|
||||
strokeWidth,
|
||||
strokeCap,
|
||||
)
|
||||
}
|
||||
if ((secondLineHead - secondLineTail) > 0) {
|
||||
drawLinearIndicator(
|
||||
secondLineHead,
|
||||
secondLineTail,
|
||||
color,
|
||||
strokeWidth,
|
||||
strokeCap,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun Modifier.increaseSemanticsBounds(): Modifier {
|
||||
val padding = 10.dp
|
||||
return this
|
||||
|
|
@ -129,16 +222,51 @@ private fun DrawScope.drawLinearIndicator(
|
|||
private fun DrawScope.drawLinearIndicatorBackground(color: Color, strokeWidth: Float, strokeCap: StrokeCap) =
|
||||
drawLinearIndicator(0f, 1f, color, strokeWidth, strokeCap)
|
||||
|
||||
// Indeterminate linear indicator transition specs
|
||||
// Total duration for one cycle
|
||||
private const val LINEAR_ANIMATION_DURATION = 1800
|
||||
|
||||
// Duration of the head and tail animations for both lines
|
||||
private const val FIRST_LINE_HEAD_DURATION = 750
|
||||
private const val FIRST_LINE_TAIL_DURATION = 850
|
||||
private const val SECOND_LINE_HEAD_DURATION = 567
|
||||
private const val SECOND_LINE_TAIL_DURATION = 533
|
||||
|
||||
// Delay before the start of the head and tail animations for both lines
|
||||
private const val FIRST_LINE_HEAD_DELAY = 0
|
||||
private const val FIRST_LINE_TAIL_DELAY = 333
|
||||
private const val SECOND_LINE_HEAD_DELAY = 1000
|
||||
private const val SECOND_LINE_TAIL_DELAY = 1267
|
||||
|
||||
private val FIRST_LINE_HEAD_EASING = CubicBezierEasing(0.2f, 0f, 0.8f, 1f)
|
||||
private val FIRST_LINE_TAIL_EASING = CubicBezierEasing(0.4f, 0f, 1f, 1f)
|
||||
private val SECOND_LINE_HEAD_EASING = CubicBezierEasing(0f, 0f, 0.65f, 1f)
|
||||
private val SECOND_LINE_TAIL_EASING = CubicBezierEasing(0.1f, 0f, 0.45f, 1f)
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun LinearProgressIndicator_Preview() {
|
||||
TangemThemePreview {
|
||||
LinearProgressIndicator(
|
||||
progress = { 0.5f },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(TangemTheme.colors.background.secondary)
|
||||
.padding(12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||
) {
|
||||
TangemLinearProgressIndicator(
|
||||
progress = { 0.6f },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
color = TangemTheme.colors.icon.primary1,
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
)
|
||||
TangemLinearProgressIndicator(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
color = TangemTheme.colors.icon.primary1,
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
|
|
@ -17,7 +17,7 @@ import com.tangem.core.ui.components.SpacerW8
|
|||
import com.tangem.core.ui.components.TextShimmer
|
||||
import com.tangem.core.ui.components.block.information.InformationBlock
|
||||
import com.tangem.core.ui.components.buttons.segmentedbutton.SegmentedButtons
|
||||
import com.tangem.core.ui.components.progressbar.LinearProgressIndicator
|
||||
import com.tangem.core.ui.components.progressbar.TangemLinearProgressIndicator
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemAnimations
|
||||
|
|
@ -116,7 +116,7 @@ private fun Content(state: PricePerformanceUM.Value, modifier: Modifier = Modifi
|
|||
color = TangemTheme.colors.text.tertiary,
|
||||
)
|
||||
}
|
||||
LinearProgressIndicator(
|
||||
TangemLinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.height(TangemTheme.dimens.size6)
|
||||
.fillMaxWidth(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.features.onboarding.v2.stepper.impl.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.animation.core.LinearEasing
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
|
|
@ -15,7 +16,7 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.core.ui.components.appbar.TangemTopAppBar
|
||||
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
|
||||
import com.tangem.core.ui.components.progressbar.LinearProgressIndicator
|
||||
import com.tangem.core.ui.components.progressbar.TangemLinearProgressIndicator
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemAnimations
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -59,7 +60,7 @@ internal fun OnboardingStepper(
|
|||
modifier = modifier,
|
||||
)
|
||||
|
||||
LinearProgressIndicator(
|
||||
TangemLinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.alpha(progressAlpha)
|
||||
.padding(horizontal = 16.dp)
|
||||
|
|
@ -67,15 +68,16 @@ internal fun OnboardingStepper(
|
|||
.fillMaxWidth(),
|
||||
progress = { animatedIndicatorFraction },
|
||||
color = TangemTheme.colors.icon.primary1,
|
||||
backgroundColor = TangemTheme.colors.background.tertiary,
|
||||
backgroundColor = TangemTheme.colors.icon.primary1.copy(alpha = 0.4f),
|
||||
strokeCap = StrokeCap.Round,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
private fun OnboardingStepper_Preview() {
|
||||
TangemThemePreview {
|
||||
Box(
|
||||
Modifier
|
||||
|
|
|
|||
|
|
@ -1,10 +1,14 @@
|
|||
package com.tangem.feature.onboarding.api
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.StrokeCap
|
||||
import com.tangem.core.ui.components.progressbar.TangemLinearProgressIndicator
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.model.OnboardingSeedPhraseState
|
||||
import com.tangem.feature.onboarding.presentation.wallet2.ui.*
|
||||
|
|
@ -19,31 +23,22 @@ class OnboardingSeedPhraseScreen : OnboardingSeedPhraseApi {
|
|||
override fun ScreenContent(uiState: OnboardingSeedPhraseState, subScreen: SeedPhraseScreen, progress: Float) {
|
||||
BackHandler(onBack = uiState.onBackClick)
|
||||
Column {
|
||||
ProgressIndicator(progress)
|
||||
TangemLinearProgressIndicator(
|
||||
progress = { progress },
|
||||
color = TangemTheme.colors.icon.primary1,
|
||||
backgroundColor = TangemTheme.colors.icon.primary1.copy(alpha = 0.4f),
|
||||
strokeCap = StrokeCap.Round,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(top = TangemTheme.dimens.size8)
|
||||
.padding(horizontal = TangemTheme.dimens.size16),
|
||||
)
|
||||
Content(subScreen, uiState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressIndicator(progress: Float) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
.padding(top = TangemTheme.dimens.size8),
|
||||
) {
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = TangemTheme.dimens.size16),
|
||||
color = TangemTheme.colors.background.action,
|
||||
backgroundColor = TangemTheme.colors.background.action.copy(alpha = 0.081f),
|
||||
progress = progress,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Content(screen: SeedPhraseScreen, uiState: OnboardingSeedPhraseState) {
|
||||
when (screen) {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import androidx.compose.animation.AnimatedContent
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import androidx.compose.foundation.border
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue