使用Compose实现小视频app源码自定义摩天轮的效果


Layout作用
自定义布局使用Layout实现,Layout可以布局多个可组合项。我们可以通过Layout实现各种复杂的自定义布局。Column和Row都是通过Layout实现的

Layout api讲解
下面的代码摘抄自官方,实现了一个Column的效果

 

复制代码
@Composable
fun MyBasicColumn(
modifier: Modifier = Modifier,
content: @Composable () -> Unit
) {
Layout(
modifier = modifier,
content = content
) { measurables, constraints ->

//placeables是测量完的子view列表
val placeables = measurables.map { measurable ->
measurable.measure(constraints)//根据父布局约束测量
}
layout(constraints.maxWidth, constraints.maxHeight) {//maxWidth就是父布局的最大宽度,layout函数是用来布局摆放子布局的
var yPosition = 0
placeables.forEach { placeable ->
placeable.placeRelative(x = 0, y = yPosition)//根据相对位置摆放子view
yPosition += placeable.height
}
}
}
}
复制代码

 


 

content: 被传递给子项的view函数
measurables: 所有可被测量的布局列表
constraints: 来自于父布局的约束条件
实现自定义布局
本例中我们实现了这样一个效果,传入n个子布局,然后将这个子布局使用自定义布局Layout实现原型摆放的效果。代码如下

 

复制代码
@Composable
private fun startAnimLayoutReal(
modifier: Modifier = Modifier,
degree: Double,
content: @Composable () -> Unit
) {
Layout(content = content, modifier = modifier) { measurable, constraint ->
val placeable = measurable.map {
it.measure(constraint)
}
val perDegree = 2 * Math.PI / placeable.size//两个子view之间的弧度间隔
val width = 300//摆放大圆的半径
val startX = 450//圆心x坐标
val startY = 450//圆心y坐标
var currentDegree = degree//当前所属的弧度
layout(constraint.maxWidth, constraint.maxHeight) {
placeable.forEach {
val x = Math.sin(currentDegree) * width + startY
val y = Math.cos(currentDegree) * width + startX
it.placeRelative(x = x.toInt(), y = y.toInt())//根据控件当前弧度将控件摆放在大圆的对应位置上
currentDegree += perDegree.toFloat()//弧度加一,摆放下一个子布局
}
}
}
} 
复制代码

 

给布局加上摩天轮的旋转效果
我们使用rememberInfiniteTransition实现动画无限执行的效果,这样多个子view围绕之圆心进行无限旋转,看起来就像一个大摩天轮

 

复制代码
@Composable
fun starLayout() {
val size = 30.dp
Column {
buildTopBar(title = "摩天轮")
startLayoutReal {
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
Image(
modifier = Modifier.size(size),
painter = painterResource(id = R.drawable.apple),
contentDescription = ""
)
}
}

}

@Composable
private fun startLayoutReal(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
val transition = rememberInfiniteTransition()
val currentDegree by transition.animateFloat(
initialValue = 0f, targetValue = 2 * Math.PI.toFloat(), animationSpec = infiniteRepeatable(
animation = tween(10 * 1000, easing = LinearEasing),
repeatMode = RepeatMode.Restart
)
)
startAnimLayoutReal(modifier = modifier, currentDegree.toDouble(), content = content)
}

@Composable
private fun startAnimLayoutReal(
modifier: Modifier = Modifier,
degree: Double,
content: @Composable () -> Unit
) {
Layout(content = content, modifier = modifier) { measurable, constraint ->
val placeable = measurable.map {
it.measure(constraint)
}
val perDegree = 2 * Math.PI / placeable.size//两个子view之间的弧度间隔
val width = 300//摆放大圆的半径
val startX = 450//圆心x坐标
val startY = 450//圆心y坐标
var currentDegree = degree//当前所属的弧度
layout(constraint.maxWidth, constraint.maxHeight) {
placeable.forEach {
val x = Math.sin(currentDegree) * width + startY
val y = Math.cos(currentDegree) * width + startX
it.placeRelative(x = x.toInt(), y = y.toInt())//根据控件当前弧度将控件摆放在大圆的对应位置上
currentDegree += perDegree.toFloat()//弧度加一,摆放下一个子布局
}
}
}
}
复制代码

 


以上就是使用Compose实现小视频app源码自定义摩天轮的效果, 更多内容欢迎关注之后的文章

posted @   云豹科技-苏凌霄  阅读(72)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示