Android Compose 应用scale修饰符后如何消除可组合项残留空白
Jetpack Compose 中scale修饰符产生多余空白的解决方案
在实现可滚动的同比例缩放屏幕预览列表时,给全屏尺寸的可组合项添加scale修饰符缩小后,组件周围出现多余空白,无法紧贴排列,运行效果如下:
核心原因:scale 修饰符仅作用于Compose的绘制阶段,不会改变可组合项的测量占位尺寸。你代码中的ScreenVisual在测量阶段仍然占用完整的screenWidth、screenHeight的空间,仅绘制时缩小到70%,父容器Surface也会按照完整屏幕尺寸占位,自然就会在组件周围形成空白。
方案1:直接调整父Surface的占位尺寸为缩放后大小
提前计算缩放后的实际宽高,给Surface设置对应尺寸,内部预览组件保持原始全屏尺寸加scale,即可保证组件测量占位和实际绘制大小一致,消除空白。
val scaleFactor = 0.7F // 计算缩放后的实际占位尺寸 val scaledWidth = screenWidth * scaleFactor val scaledHeight = screenHeight * scaleFactor Row( modifier = Modifier.horizontalScroll(rememberScrollState()) ) { Surface( modifier = Modifier.size(scaledWidth, scaledHeight), // 给Surface设置缩放后的占位尺寸 shape = RoundedCornerShape(8.dp), color = MaterialTheme.colors.primary.copy(alpha = .2f), ) { ScreenVisual( modifier = Modifier .size(screenWidth, screenHeight) .align(Alignment.Center) // 保证缩放后的内容居中 .scale(scaleFactor) ) } // 第二个Surface同理设置即可 Surface( modifier = Modifier.size(scaledWidth, scaledHeight), shape = RoundedCornerShape(8.dp), color = MaterialTheme.colors.primary.copy(alpha = .2f), ) { OtherScreenVisual( modifier = Modifier .size(screenWidth, screenHeight) .align(Alignment.Center) .scale(scaleFactor) ) } }
方案2:使用graphicsLayer配合layout修饰符动态调整占位
如果缩放比例是动态变化的,可以通过graphicsLayer设置缩放,同时用layout修饰符动态修改测量后的占位尺寸,不需要提前计算宽高:
首先自定义修饰符:
fun Modifier.scaleAdjustLayout(scale: Float) = this .graphicsLayer( scaleX = scale, scaleY = scale ) .layout { measurable, constraints -> val placeable = measurable.measure(constraints) // 调整占位尺寸为缩放后的大小 val scaledWidth = (placeable.width * scale).roundToInt() val scaledHeight = (placeable.height * scale).roundToInt() layout(scaledWidth, scaledHeight) { // 内容居中放置 placeable.placeRelative( x = (scaledWidth - placeable.width) / 2, y = (scaledHeight - placeable.height) / 2 ) } }
使用时直接替换原来的scale修饰符即可:
ScreenVisual( modifier = Modifier .size(screenWidth, screenHeight) .scaleAdjustLayout(0.7F) )
两种方案都可以实现组件紧贴排列的效果,方案1实现简单适合固定缩放比例的场景,方案2灵活性更高适合动态缩放的场景。
内容的提问来源于stack exchange,提问作者Chompions Sawelo
相关产品推荐
相关产品推荐

