Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-13 17:06:15 +03:00
parent 93abd29e1a
commit ae2edc7fbf
2 changed files with 95 additions and 24 deletions

View file

@ -1,14 +1,15 @@
package com.tangem.core.ui.components
import androidx.annotation.FloatRange
import androidx.compose.material.LocalTextStyle
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.sp
@ -54,6 +55,63 @@ fun ResizableText(
)
}
/**
* A Composable function that displays text which can be resized based on its content's overflow.
*
* This function draws text on the screen and checks if it overflows. If the text overflows,
* its font size is reduced recursively until it either fits the available space or reaches a
* specified minimum font size.
*/
@Composable
fun ResizableText(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
textAlign: TextAlign? = null,
overflow: TextOverflow = TextOverflow.Clip,
softWrap: Boolean = true,
maxLines: Int = Int.MAX_VALUE,
style: TextStyle = LocalTextStyle.current,
minFontSize: TextUnit = TextUnit.Unspecified,
@FloatRange(from = 0.0, to = 1.0, fromInclusive = false, toInclusive = false)
reduceFactor: Double = 0.9,
) {
var fontSize by remember { mutableStateOf(style.fontSize) }
var readyToDraw by remember { mutableStateOf(value = false) }
Text(
modifier = modifier.drawWithContent {
if (readyToDraw) drawContent()
},
text = text,
color = color,
fontSize = fontSize,
textAlign = textAlign,
overflow = overflow,
softWrap = softWrap,
maxLines = maxLines,
style = style,
onTextLayout = { result ->
fun reduceFontSize() {
val reducedFontSize = fontSize * reduceFactor
if (minFontSize != TextUnit.Unspecified && reducedFontSize <= minFontSize) {
fontSize = minFontSize
readyToDraw = true
} else {
fontSize = reducedFontSize
}
}
if (result.hasVisualOverflow) {
reduceFontSize()
} else {
readyToDraw = true
}
},
)
}
data class FontSizeRange(
val min: TextUnit,
val max: TextUnit,

View file

@ -1,20 +1,19 @@
package com.tangem.core.ui.components.buttons.common
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.requiredSizeIn
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.tangem.core.ui.components.SpacerW
import androidx.compose.ui.unit.sp
import com.tangem.core.ui.components.ResizableText
import com.tangem.core.ui.res.TangemTheme
@Suppress("LongParameterList")
@ -40,31 +39,35 @@ fun TangemButton(
colors = colors,
contentPadding = size.toContentPadding(icon = icon),
) {
val maxContentSize = getMaxButtonContentSize(buttonTextStyle = textStyle)
ButtonContentContainer(
buttonIcon = icon,
iconPadding = size.toIconPadding(),
showProgress = showProgress,
progressIndicator = {
CircularProgressIndicator(
modifier = Modifier.buttonContentSize(textStyle),
modifier = Modifier.buttonContentSize(maxContentSize),
color = colors.contentColor(enabled = enabled).value,
strokeWidth = TangemTheme.dimens.size4,
)
},
text = {
Text(
modifier = Modifier.alignByBaseline(),
ResizableText(
modifier = Modifier
.weight(1f, fill = false)
.heightIn(MinButtonContentSize, maxContentSize),
text = text,
style = textStyle,
color = colors.contentColor(enabled = enabled).value,
textAlign = TextAlign.Center,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
minFontSize = 12.sp,
)
},
icon = { iconResId ->
Icon(
modifier = Modifier.buttonContentSize(textStyle),
modifier = Modifier.buttonContentSize(maxContentSize),
painter = painterResource(id = iconResId),
tint = colors.contentColor(enabled = enabled).value,
contentDescription = null,
@ -89,26 +92,36 @@ private inline fun RowScope.ButtonContentContainer(
} else {
if (buttonIcon is TangemButtonIconPosition.Start) {
icon(buttonIcon.iconResId)
SpacerW(width = iconPadding)
Spacer(modifier = Modifier.requiredWidth(iconPadding))
}
text()
if (buttonIcon is TangemButtonIconPosition.End) {
SpacerW(width = iconPadding)
Spacer(modifier = Modifier.requiredWidth(iconPadding))
icon(buttonIcon.iconResId)
}
}
}
private fun Modifier.buttonContentSize(buttonTextStyle: TextStyle): Modifier = composed {
val minContentElementSize = TangemTheme.dimens.size20
val maxContentElementSize = remember(key1 = buttonTextStyle.lineHeight) {
buttonTextStyle.lineHeight.value.dp + 4.dp
private val MinButtonContentSize: Dp
@Composable
@ReadOnlyComposable
get() = TangemTheme.dimens.size20
@Composable
@ReadOnlyComposable
private fun getMaxButtonContentSize(buttonTextStyle: TextStyle): Dp {
val buttonLineHeight = with(LocalDensity.current) {
buttonTextStyle.lineHeight.toDp()
}
return buttonLineHeight.coerceAtLeast(MinButtonContentSize)
}
private fun Modifier.buttonContentSize(maxSize: Dp): Modifier = composed {
this.requiredSizeIn(
minWidth = minContentElementSize,
minHeight = minContentElementSize,
maxWidth = maxContentElementSize,
maxHeight = maxContentElementSize,
minWidth = MinButtonContentSize,
minHeight = MinButtonContentSize,
maxWidth = maxSize,
maxHeight = maxSize,
)
}