Compose库升级至最新版本后,内部字段无法访问的错误如何修复?
Compose升级后内部API访问错误的修复方案
一、SwipeButton组件修复
问题场景
升级Compose库后,ButtonColors和ButtonElevation的部分方法被标记为内部API,直接调用contentColor()、containerColor()、shadowElevation()、tonalElevation()会触发访问权限错误。
报错信息
Cannot access 'contentColor': it is internal in 'ButtonColors' Cannot access 'containerColor': it is internal in 'ButtonColors' Cannot access 'shadowElevation': it is internal in 'ButtonElevation' Cannot access 'tonalElevation': it is internal in 'ButtonElevation'
修复后的代码
@Composable fun SwipeButton( onSwiped: () -> Unit, modifier: Modifier = Modifier, swipeButtonState: SwipeButtonState, enabled: Boolean = true, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, elevation: ButtonElevation? = ButtonDefaults.buttonElevation(), shape: Shape = RoundedCornerShape(20.0.dp), border: BorderStroke? = null, colors: ButtonColors = ButtonDefaults.buttonColors(), contentPadding: PaddingValues = ButtonDefaults.ContentPadding, icon: ImageVector = Icons.Default.ArrowForward, rotateIcon: Boolean = true, iconPadding: PaddingValues = PaddingValues(2.dp), content: @Composable RowScope.() -> Unit ) { // 替换原内部API调用,使用公开的resolve方法获取颜色和elevation结果 val buttonColorsResult by remember(enabled, interactionSource) { derivedStateOf { colors.resolve(enabled, interactionSource) } } val contentColor = buttonColorsResult.contentColor val elevationResult by remember(enabled, interactionSource) { derivedStateOf { elevation?.resolve(enabled, interactionSource) } } val dragOffset = remember { mutableStateOf(0f) } val collapsed = swipeButtonState == SwipeButtonState.COLLAPSED val swiped = swipeButtonState == SwipeButtonState.SWIPED Surface( modifier = modifier, shape = shape, color = buttonColorsResult.containerColor, contentColor = contentColor.copy(alpha = 1f), border = border, shadowElevation = elevationResult?.shadowElevation ?: 0.dp, tonalElevation = elevationResult?.tonalElevation ?: 0.dp, ) { BoxWithConstraints( modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.CenterStart ) { // Content val maxWidth = this.constraints.maxWidth.toFloat() when { collapsed -> { val animatedProgress = remember { Animatable(initialValue = 0f) } LaunchedEffect(Unit) { animatedProgress.animateTo( targetValue = 1f, animationSpec = tween(600) ) } IconButton( onClick = { }, modifier = Modifier .scale(animatedProgress.value) .padding(iconPadding) .clip(CircleShape) .background(MaterialTheme.colorScheme.onPrimary) .align(Alignment.Center) ) { Icon( imageVector = Icons.Default.Done, contentDescription = "Done", tint = MaterialTheme.colorScheme.primary ) } } swiped -> { HorizontalDottedProgressBar() } else -> { dragOffset.value = 0f // 重置为初始状态 CompositionLocalProvider(LocalContentAlpha provides contentColor.alpha) { ProvideTextStyle( value = MaterialTheme.typography.bodyMedium ) { Row( Modifier .fillMaxSize() .padding(contentPadding), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, content = content ) } } } } // Swipe Component AnimatedVisibility(visible = !swiped) { IconButton(onClick = { }, enabled = enabled, modifier = Modifier .padding(iconPadding) .align(Alignment.CenterStart) .offset { IntOffset(dragOffset.value.roundToInt(), 0) } .draggable( enabled = enabled, orientation = Orientation.Horizontal, state = rememberDraggableState { delta -> val newValue = dragOffset.value + delta dragOffset.value = newValue.coerceIn(0f, maxWidth) }, onDragStopped = { if (dragOffset.value > maxWidth * 2 / 3) { dragOffset.value = maxWidth onSwiped.invoke() } else { dragOffset.value = 0f } } ) .background(MaterialTheme.colorScheme.onPrimary, shape = CircleShape) ) { Icon( imageVector = icon, modifier = Modifier.graphicsLayer { if (rotateIcon) { rotationZ += dragOffset.value / 5 } }, contentDescription = "Arrow", tint = buttonColorsResult.containerColor, ) } } } } }
修复说明
- 使用
ButtonColors.resolve(enabled, interactionSource)获取公开的颜色结果对象,替代直接调用内部的contentColor()和containerColor()方法 - 使用
ButtonElevation.resolve(enabled, interactionSource)获取公开的elevation结果对象,替代直接调用内部的shadowElevation()和tonalElevation()方法 - 通过
remember和derivedStateOf确保状态随enabled和interactionSource变化自动更新
二、BottomSheetDrawer组件修复
问题场景
升级Compose库后,ModalBottomSheetState的isAnimationRunning属性被标记为内部API,直接访问会触发权限错误。
报错信息
Cannot access 'isAnimationRunning': it is internal in 'ModalBottomSheetState'
修复后的代码
@Composable fun BottomSheetDrawer() { val bottomSheetScaffoldState = rememberBottomSheetScaffoldState() val coroutineScope = rememberCoroutineScope() val sheetState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden) BottomSheetScaffold( drawerBackgroundColor = MaterialTheme.colorScheme.surface, sheetBackgroundColor = MaterialTheme.colorScheme.surface, backgroundColor = MaterialTheme.colorScheme.background, content = { Box { ScafoldContent(coroutineScope, bottomSheetScaffoldState, sheetState) } }, sheetContent = { PlayerBottomSheet() }, drawerContent = { DrawerContent() }, scaffoldState = bottomSheetScaffoldState, // 替换内部属性isAnimationRunning,通过对比currentValue和targetValue检测动画状态 sheetPeekHeight = if (sheetState.isVisible || sheetState.currentValue != sheetState.targetValue) 0.dp else 65.dp, ) }
修复说明
- 原内部属性
isAnimationRunning用于检测底部抽屉是否处于动画过渡中,可通过对比currentValue和targetValue实现等价逻辑:当两者不一致时,说明组件正在执行动画过渡 - 保留
isVisible判断抽屉已完全展开的场景,结合过渡状态判断,完整复现原逻辑
内容的提问来源于stack exchange,提问作者AndreaF
相关产品推荐
相关产品推荐

