对于用过一段时间的 Compose 开发者来说,Compose 目前在完善性上还有一些差距,比如原生的 ToolTips,当然网上也有很多库用来支持,但我觉得有点大材小用。
毕竟,一个 ToolTips 只需要排列一下,然后一定时间内消失就行,于是自己写一下吧,不考虑边界还是灰常简单的~
主要拆解为四个部分:
一些基础属性定义:
private var basePositionMap = mutableMapOf<String, Offset>() private var baseSizeMap = mutableMapOf<String, IntSize>() private var tips by mutableStateOf("") private var tipsDismissJob: Job? = null
Modifier 修饰符定义,主要是监听手势操作:
@Stable fun Modifier.toolTips( onClick: () -> Unit, desc: String ) = this.then( Modifier .onGloballyPositioned { basePositionMap[desc] = it.positionInRoot() baseSizeMap[desc] = it.size } .pointerInput(Unit) { detectTapGestures(onTap = { onClick.invoke() }, onLongPress = { tips = desc }) } )
ToolTips 控件本身:
@Composable fun ToolTips(content: @Composable () -> Unit = { DefaultToolTips() }) { if (tips.isNotEmpty()) { ToolTipsBox(Modifier) { content() } } val scope = LocalLifecycleOwner.current.lifecycleScope LaunchedEffect(tips) { tipsDismissJob?.cancel() tipsDismissJob = scope.launch { delay(2000) if (isActive) { tips = "" } } } }
默认 ToolTips 样式:
@Composable fun DefaultToolTips() { Box( modifier = Modifier .clip(Shapes2) .background(color = colorResource(id = R.color.colorOnContent)) .padding(horizontal = 8.dp, vertical = 4.dp) ) { Text(text = tips, fontSize = 12.sp, color = colorResource(id = R.color.colorContent)) } }
用于布局 TipsBox 位置:
@Composable private fun ToolTipsBox( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { val position = basePositionMap[tips] ?: return val size = baseSizeMap[tips] ?: return val y = with(LocalDensity.current) { position.y + 32.dp.toPx() } Layout( modifier = modifier, content = content ) { measurables, constraints -> val placeables = measurables.map { measurable -> measurable.measure(constraints) } layout(constraints.minWidth, constraints.minHeight) { placeables.forEach { placeable -> placeable.placeRelative(x = (position.x - placeable.width / 2f + size.width / 2f).toInt(), y = y.toInt()) } } } }
用法:
setContent { Box(modifier = Modifier.fillMaxWidth()) { val contentDescription = "描述文字" Icon( modifier = Modifier //... .toolTips(onClick = { //... }, contentDescription) ) ToolTips() } }
至于思路,就是存下了长按控件的位置、大小,然后再根据这个位置布局一下 ToolTips 的位置,最后这个 ToolTips 会在一定时间后消失,就这么简单。
但真用起来,其实问题不少,比如可能超过父布局边界,比如可能需要换个方位,就自行调整或者直接用别人设计的更具备实用性的库吧,毕竟我这就图个轻便~
以上!
本站由以下主机服务商提供服务支持:
0条评论