You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Wear OS Compose中Chip适配系统字体大小的实现问题

Wear OS Jetpack Compose Chip 适配系统字体大小问题修复

问题现象

使用Jetpack Compose开发Wear OS应用时,Chip组件在系统字体设为默认时显示正常,但调至最大字号时,Chip内的文字会溢出底部,无法自适应调整组件高度。

原代码

fun MainScreen(
    userPreferences: SharedPreferences,
    oneTrainingsOnClick: () -> Unit,
    freeTrainingOnClick: () -> Unit,
    settingsOnClick: () -> Unit,
    signInOnClick: () -> Unit
) {
    val isUserLoggedIn = userPreferences.getBoolean(MainActivity.LOG_IN, false)
    val chipColor = colorResource(id = R.color.gray)

    val listState = rememberScalingLazyListState(initialCenterItemIndex = 0)
    val coroutineScope = rememberCoroutineScope()
    val focusRequester = remember { FocusRequester() }

    Scaffold(
        positionIndicator = { PositionIndicator(scalingLazyListState = listState) },
        timeText = { TimeOnList(listState) },
        vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) }
    ) {
        ScalingLazyColumn(
            state = listState,
            modifier = Modifier
                .fillMaxSize()
                .onRotaryScrollEvent {
                    coroutineScope.launch { listState.scrollBy(it.verticalScrollPixels) }
                    true
                }
                .focusRequester(focusRequester)
                .focusable()
        ) {
            item {
                Chip(
                    icon = {
                        Image(
                            painter = painterResource(id = R.drawable.ic_one_icon),
                            contentDescription = null
                        )
                    },
                    onClick = {
                        if (isUserLoggedIn) oneTrainingsOnClick() else signInOnClick()
                    },
                    enabled = true,
                    colors = ChipDefaults.chipColors(chipColor),
                    modifier = Modifier
                        .wrapContentSize()
                        .fillMaxWidth()
                        .padding(top = 40.dp),
                    shape = RoundedCornerShape(30.dp),
                    label = {
                        Text(
                            text =
                            if (isUserLoggedIn) stringResource(id = R.string.one_trainings_button)
                            else stringResource(id = R.string.start),
                            style = TextStyle(
                                textAlign = TextAlign.Left,
                                fontFamily = Font(R.font.roboto_bold).toFontFamily(),
                                fontSize = dimensionResource(id = R.dimen.general_text).value.sp,
                                color = colorResource(id = R.color.white)
                            ),
                            maxLines = 2,
                            modifier = Modifier.fillMaxWidth()
                        )
                    },
                )
            }
            item {
                Chip(
                    icon = {
                        Image(
                            painter = painterResource(id = R.drawable.ic_free_training),
                            contentDescription = null
                        )
                    },
                    onClick = { freeTrainingOnClick() },
                    colors = ChipDefaults.chipColors(chipColor),
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(30.dp),
                    label = {
                        Text(
                            text = stringResource(id = R.string.free_training_button),
                            style = TextStyle(
                                textAlign = TextAlign.Left,
                                fontFamily = Font(R.font.roboto_bold).toFontFamily(),
                                fontSize = dimensionResource(id = R.dimen.general_text).value.sp,
                                color = colorResource(id = R.color.white)
                            ),
//                            overflow = TextOverflow.Ellipsis,
//                            maxLines = 1,
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                )
            }
            item {
                Chip(
                    icon = {
                        Image(
                            painter = painterResource(id = R.drawable.ic_settings),
                            contentDescription = null
                        )
                    },
                    onClick = { settingsOnClick() },
                    colors = ChipDefaults.chipColors(chipColor),
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(30.dp),
                    label = {
                        Text(
                            text = stringResource(id = R.string.configuration_text),
                            maxLines = 1,
                            style = TextStyle(
                                textAlign = TextAlign.Left,
                                fontFamily = Font(R.font.roboto_bold).toFontFamily(),
                                fontSize = dimensionResource(id = R.dimen.general_text).value.sp,
                                color = colorResource(id = R.color.white)
                            ),
                            overflow = TextOverflow.Ellipsis,
                            modifier = Modifier.fillMaxWidth()
                        )
                    },
                    secondaryLabel = {
                        Text(text = stringResource(id = R.string.failed_authentication))
                    }
                )
            }
        }
        LaunchedEffect(Unit) { focusRequester.requestFocus() }
    }
}

修复方案

  • 正确适配系统字体缩放:原代码中通过dimensionResource(id = R.dimen.general_text).value.sp设置字号的方式错误,会丢失系统字体缩放比例。直接使用dimensionResource作为fontSize值(确保general_text在dimens.xml中定义为sp单位),系统会自动应用字体缩放。
  • 让Chip自适应高度:移除Chip上不必要的wrapContentSize()修饰符,保留fillMaxWidth()让组件占满宽度,同时允许高度根据内容自动调整。
  • 合理设置文本换行规则:根据文本长度设置合适的maxLines,避免强制单行导致溢出;对于不需要换行的文本,保留TextOverflow.Ellipsis防止溢出。

修改后的代码

fun MainScreen(
    userPreferences: SharedPreferences,
    oneTrainingsOnClick: () -> Unit,
    freeTrainingOnClick: () -> Unit,
    settingsOnClick: () -> Unit,
    signInOnClick: () -> Unit
) {
    val isUserLoggedIn = userPreferences.getBoolean(MainActivity.LOG_IN, false)
    val chipColor = colorResource(id = R.color.gray)

    val listState = rememberScalingLazyListState(initialCenterItemIndex = 0)
    val coroutineScope = rememberCoroutineScope()
    val focusRequester = remember { FocusRequester() }

    // 复用文本样式,避免重复代码
    val chipTextStyle = TextStyle(
        textAlign = TextAlign.Left,
        fontFamily = Font(R.font.roboto_bold).toFontFamily(),
        fontSize = dimensionResource(id = R.dimen.general_text), // 直接使用dimensionResource适配缩放
        color = colorResource(id = R.color.white)
    )

    Scaffold(
        positionIndicator = { PositionIndicator(scalingLazyListState = listState) },
        timeText = { TimeOnList(listState) },
        vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) }
    ) {
        ScalingLazyColumn(
            state = listState,
            modifier = Modifier
                .fillMaxSize()
                .onRotaryScrollEvent {
                    coroutineScope.launch { listState.scrollBy(it.verticalScrollPixels) }
                    true
                }
                .focusRequester(focusRequester)
                .focusable()
        ) {
            item {
                Chip(
                    icon = {
                        Image(
                            painter = painterResource(id = R.drawable.ic_one_icon),
                            contentDescription = null
                        )
                    },
                    onClick = {
                        if (isUserLoggedIn) oneTrainingsOnClick() else signInOnClick()
                    },
                    enabled = true,
                    colors = ChipDefaults.chipColors(chipColor),
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 40.dp), // 移除不必要的wrapContentSize
                    shape = RoundedCornerShape(30.dp),
                    label = {
                        Text(
                            text = if (isUserLoggedIn) stringResource(id = R.string.one_trainings_button)
                            else stringResource(id = R.string.start),
                            style = chipTextStyle,
                            maxLines = 2, // 允许两行换行,避免溢出
                            modifier = Modifier.fillMaxWidth()
                        )
                    },
                )
            }
            item {
                Chip(
                    icon = {
                        Image(
                            painter = painterResource(id = R.drawable.ic_free_training),
                            contentDescription = null
                        )
                    },
                    onClick = { freeTrainingOnClick() },
                    colors = ChipDefaults.chipColors(chipColor),
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(30.dp),
                    label = {
                        Text(
                            text = stringResource(id = R.string.free_training_button),
                            style = chipTextStyle,
                            maxLines = 2, // 允许换行
                            modifier = Modifier.fillMaxWidth()
                        )
                    }
                )
            }
            item {
                Chip(
                    icon = {
                        Image(
                            painter = painterResource(id = R.drawable.ic_settings),
                            contentDescription = null
                        )
                    },
                    onClick = { settingsOnClick() },
                    colors = ChipDefaults.chipColors(chipColor),
                    modifier = Modifier.fillMaxWidth(),
                    shape = RoundedCornerShape(30.dp),
                    label = {
                        Text(
                            text = stringResource(id = R.string.configuration_text),
                            style = chipTextStyle,
                            maxLines = 1,
                            overflow = TextOverflow.Ellipsis, // 单行时用省略号防止溢出
                            modifier = Modifier.fillMaxWidth()
                        )
                    },
                    secondaryLabel = {
                        Text(
                            text = stringResource(id = R.string.failed_authentication),
                            style = chipTextStyle.copy(fontSize = dimensionResource(id = R.dimen.smaller_text)) // 次级文本字号可单独设置
                        )
                    }
                )
            }
        }
        LaunchedEffect(Unit) { focusRequester.requestFocus() }
    }
}

额外注意事项

  • 确认res/values/dimens.xml中general_text的定义为sp单位,例如:<dimen name="general_text">16sp</dimen>,这样系统字体缩放时会同步调整字号。
  • Wear OS的Chip组件默认已经支持自适应内容高度,只要不强制固定高度,就能随文本大小变化自动调整。

内容的提问来源于stack exchange,提问作者Santiago Melo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:34:59