kotlin 文本可组合dimensionResource不作为fontSize参数工作

isr3a4wc  于 2023-06-06  发布在  Kotlin
关注(0)|答案(6)|浏览(176)

当我插入fontSize = dimensionResource(id = R.dimen.textLabelTextSize),其中dimens或54sp或60sp取决于设备时,我在Text()上得到一个错误“下面的函数都不能用提供的参数调用。”但是当我输入一个硬编码值,如54sp时,它就没问题了。奇怪的是填充修饰符dimensionResource(在dp中)工作正常。

Text(
                text = textLabelItem.textLabel,
                modifier = Modifier
                    .padding(
                        start = dimensionResource(id = R.dimen.textLabelPaddingVertical),
                        top = dimensionResource(id = R.dimen.textLabelPaddingHorizontalTop),
                        end = dimensionResource(id = R.dimen.textLabelPaddingVertical),
                        bottom = dimensionResource(id = R.dimen.textLabelPaddingHorizontalBottom)
                    )
                    .background(colorResource(id = R.color.textLabelBg))
                    .border(
                        width = 2.dp,
                        color = colorResource(id = R.color.textLabelBorder),
                        shape = RoundedCornerShape(8.dp)
                    ),
                color = colorResource(id = android.R.color.background_dark),
                fontSize = dimensionResource(id = R.dimen.textLabelTextSize),
                fontWeight = FontWeight.Bold
            )
u7up0aaq

u7up0aaq1#

答案很简单,你只是忘记了处理dimensionResource的结果。你只需要使用它的value就可以让它成为float。然后使用sp扩展,就可以开始了。
我为此创建了自己的扩展:

@Composable
@ReadOnlyComposable
fun fontDimensionResource(@DimenRes id: Int) = dimensionResource(id = id).value.sp

因此,使用fontDimensionResource(R.dimen.your_font_size)代替dimensionResource(R.dimen.your_font_size)
最终溶液:

Text(text = "", fontSize = fontDimensionResource(id = R.dimen.your_font_size))
o2g1uqev

o2g1uqev2#

要从dp转换为sp您需要考虑字体缩放-这是使用sp进行文本的要点。这意味着当用户更改系统字体比例时,应用程序会响应此更改。

不缩放文本

如果我们在Kotlin中请求dimensionResource(),我们得到的dp值还没有缩放。您可以在源代码中确认这一点,其中该函数被定义为返回Dp

fun dimensionResource(@DimenRes id: Int): Dp {.....}

value.sp * 的基本转换不会应用所需的缩放 *,因此任何依赖于这种基本计算的解决方案都无法正常工作。

unscaledSize = dimensionResource(R.dimen.sp_size).value.sp

(其中R.dimen.sp_size是使用sp大小调整声明的维度资源)
这将无法正确缩放文本大小。

更好的解决方案

为了正确地执行,我们需要查看DisplayMetrics和当前scaledDensity值,定义为:

/**
* A scaling factor for fonts displayed on the display.  This is the same
* as {@link #density}, except that it may be adjusted in smaller
* increments at runtime based on a user preference for the font size.
*/
public float scaledDensity;

这个缩放值必须应用于获取的维度,以返回可用作sp的内容:

val scaledSize = with(LocalContext.current.resources) {
    (getDimension(R.dimen.sp_size) / displayMetrics.scaledDensity).sp
}

**警告:**此操作仅适用于定义为sp的尺寸!

不同维度类型的处理

一个更好的解决方案是检查正在访问的维度资源的类型,然后基于此进行计算,即dpsppx
这确实需要使用TypedValueTypedArray,这使得它有点复杂,但是可以在MDC主题适配器的TypedArrayUtils中找到示例代码:

internal fun TypedArray.getTextUnitOrNull(
    index: Int,
    density: Density
): TextUnit? {
    val tv = tempTypedValue.getOrSet { TypedValue() }
    if (getValue(index, tv) && tv.type == TypedValue.TYPE_DIMENSION) {
        return when (tv.complexUnitCompat) {
            // For SP values, we convert the value directly to an TextUnit.Sp
            TypedValue.COMPLEX_UNIT_SP -> TypedValue.complexToFloat(tv.data).sp
            // For DIP values, we convert the value to an TextUnit.Em (roughly equivalent)
            TypedValue.COMPLEX_UNIT_DIP -> TypedValue.complexToFloat(tv.data).em
            // For another other types, we let the TypedArray flatten to a px value, and
            // we convert it to an Sp based on the current density
            else -> with(density) { getDimension(index, 0f).toSp() }
        }
    }
    return null
}

最佳方案

理想情况下,我们不应该在使用Compose时提取资源并转换它们。我们应该使用主题常量。
我们可能都在这个页面上,因为我们有一些XML布局和其他的撰写。我们可能正在经历转换过程。
处理此类转换的最佳方法是使用Material Components MDC-Android Compose Theme Adapter来处理所有这些情况。
它的工作原理不仅仅是一个文本大小计算,这是我们应该在我们迁移到撰写的一部分。

8yoxcaq7

8yoxcaq73#

这是因为函数**dimensionResource**返回Dp值,而fontSize使用Sp值。
目前你不能使用它。

dzjeubhm

dzjeubhm4#

方法dimensionResource返回dp值。要从中获得sp值,请在末尾添加.value.sp,如下所示:
fontSize = dimensionResource(id = R.dimen.textLabelTextSize).value.sp

uz75evzq

uz75evzq5#

考虑创建此

@OptIn(ExperimentalUnitApi::class)
@Composable
@ReadOnlyComposable
fun textSizeResource(@DimenRes id: Int): TextUnit {
    val context = LocalContext.current
    val density = LocalDensity.current
    val pxValue = context.resources.getDimension(id)
    return TextUnit(pxValue / density.density, TextUnitType.Sp)
}

并按如下方式使用它

Text(text = "abc", fontSize = textSizeResource(id = R.dimen.text_large))
dffbzjpn

dffbzjpn6#

从维数中得到sp的正确方法是

Text(
    fontSize = with(LocalDensity.current) {
        dimensionResource(R.dimen.textLabelTextSize).toSp()
    }
)

以下是文档:https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density#(androidx.compose.ui.unit.Dp).toSp()

相关问题