feat(ui): Animate icon changes with Crossfade (#4028)

This commit is contained in:
James Rich
2025-12-17 14:16:56 -06:00
committed by GitHub
parent 16700bfffb
commit 212bcfd945
3 changed files with 41 additions and 31 deletions

View File

@@ -22,6 +22,7 @@ package com.geeksville.mesh.ui
import android.Manifest
import android.os.Build
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
@@ -413,11 +414,14 @@ fun MainScreen(uIViewModel: UIViewModel = hiltViewModel(), scanModel: BTScanMode
}
},
) {
Icon(
imageVector = destination.icon,
contentDescription = stringResource(destination.label),
tint = LocalContentColor.current,
)
Crossfade(isSelected, label = "BottomBarIcon") { isSelectedState ->
Icon(
imageVector = destination.icon,
contentDescription = stringResource(destination.label),
tint =
if (isSelectedState) colorScheme.primary else LocalContentColor.current,
)
}
}
}
}

View File

@@ -17,6 +17,7 @@
package com.geeksville.mesh.ui.connections.components
import androidx.compose.animation.Crossfade
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Bluetooth
import androidx.compose.material.icons.rounded.Cached
@@ -61,20 +62,22 @@ fun ConnectionsNavIcon(
val foregroundPainter = connectionTypeIcon?.let { rememberVectorPainter(it) }
Icon(
imageVector = backgroundIcon,
contentDescription = contentDescription,
tint = tint,
modifier =
modifier.drawWithContent {
drawContent()
foregroundPainter?.let {
@Suppress("MagicNumber")
val badgeSize = size.width * .45f
with(it) { draw(Size(badgeSize, badgeSize), colorFilter = ColorFilter.tint(tint)) }
}
},
)
Crossfade(targetState = backgroundIcon, label = "ConnectionIcon") {
Icon(
imageVector = it,
contentDescription = contentDescription,
tint = tint,
modifier =
modifier.drawWithContent {
drawContent()
foregroundPainter?.let {
@Suppress("MagicNumber")
val badgeSize = size.width * .45f
with(it) { draw(Size(badgeSize, badgeSize), colorFilter = ColorFilter.tint(tint)) }
}
},
)
}
}
@Composable

View File

@@ -18,6 +18,7 @@
package org.meshtastic.feature.messaging.component
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material.icons.Icons
@@ -75,18 +76,20 @@ private fun ReplyButton(onClick: () -> Unit = {}) = IconButton(
private fun MessageStatusButton(onStatusClick: () -> Unit = {}, status: MessageStatus, fromLocal: Boolean) =
AnimatedVisibility(visible = fromLocal) {
IconButton(onClick = onStatusClick) {
Icon(
imageVector =
when (status) {
MessageStatus.RECEIVED -> Icons.TwoTone.HowToReg
MessageStatus.QUEUED -> Icons.TwoTone.CloudUpload
MessageStatus.DELIVERED -> Icons.TwoTone.CloudDone
MessageStatus.ENROUTE -> Icons.TwoTone.Cloud
MessageStatus.ERROR -> Icons.TwoTone.CloudOff
else -> Icons.TwoTone.Warning
},
contentDescription = stringResource(Res.string.message_delivery_status),
)
Crossfade(targetState = status, label = "MessageStatusIcon") { currentStatus ->
Icon(
imageVector =
when (currentStatus) {
MessageStatus.RECEIVED -> Icons.TwoTone.HowToReg
MessageStatus.QUEUED -> Icons.TwoTone.CloudUpload
MessageStatus.DELIVERED -> Icons.TwoTone.CloudDone
MessageStatus.ENROUTE -> Icons.TwoTone.Cloud
MessageStatus.ERROR -> Icons.TwoTone.CloudOff
else -> Icons.TwoTone.Warning
},
contentDescription = stringResource(Res.string.message_delivery_status),
)
}
}
}