compose SubcomposeLayout 初体验之获取组件高度实现平移动画

295 阅读1分钟

@Composable
private fun createBottomTransView(
    duration:Int,
    content:@Composable ()->Unit
){
    var isTrans by remember {
        mutableStateOf(true)
    }
    val transPercent by animateFloatAsState(
        targetValue = if(isTrans) 0f else 1f,
        animationSpec = tween(durationMillis = duration * 1000, easing = FastOutLinearInEasing )
    )
    //Q这里的modifier 如果不设置高度 默认是充满全屏??
    SubcomposeLayout(modifier = Modifier
        .fillMaxWidth()
        .wrapContentHeight()
        .background(color = Color.Green), 
        measurePolicy = { constraints ->

        //测量内容高度
        val placeables = subcompose("content") {
            content()
        }.map {
            it.measure(constraints)
        }
        if(placeables.size > 1) throw Exception("只能有一个节点")
        val result = layout(constraints.maxWidth,constraints.maxHeight){
            placeables.forEach { place->
                //放置在最底部
                place.placeRelative(0,  (constraints.maxHeight - place.height * transPercent).toInt())
            }
        }
        return@SubcomposeLayout result
    })

    LaunchedEffect(key1 = Unit){
        ILogUtils.e("LaunchedEffect")
        isTrans = false
    }
}

知识点1 measurePolicy 的参数 constraints 是结合父节点对SubcomposeLayout的约束以及SubcomposeLayout自己的Modifier调整得出来的。并且SubcomposeLayout 的 Modifier 的优先级 更高。

比如 SubcomposeLayout 的 modifier = Modifier 什么也不设置那么尺寸如下,最小0 最大就是父节点的尺寸。

image.png

比如modifier = Modifier.width(100.dp).height(100.dp) 那么输出如下 就是自己设置的尺寸

image.png

知识点2 subcompose("content") { content() } 这里返回的是一个list,这里有List有多少个元素取决于content()中有多少个顶层组件。也就是直接在@Composable 代码块内声明,没有被任何其他可组合组件包裹的组件。

知识点3 layout(constraints.maxWidth,constraints.maxHeight)这个地方决定了最终SubcomposeLayout的尺寸大小。

所以说SubcomposeLayout的作用就是拿着父节点给的约束,测量所有子节点的尺寸,然后根据所有字节点的尺寸计算SubcomposeLayout最终的尺寸。