首页动画完成

This commit is contained in:
2024-10-11 20:46:40 +08:00
parent 81f90db1b1
commit 58a1824e80

View File

@@ -1,6 +1,7 @@
package com.aiosman.riderpro.ui.login
import android.content.ContentValues.TAG
import android.content.res.Resources
import android.util.Log
import android.widget.Toast
import androidx.compose.animation.core.LinearEasing
@@ -9,6 +10,10 @@ import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.rememberScrollableState
import androidx.compose.foundation.gestures.scrollable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -23,7 +28,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
@@ -145,11 +152,13 @@ fun LoginPage() {
Box(
modifier = Modifier
.fillMaxSize()
.offset(
y = (-72).dp
),
// .offset(
// y = (-72).dp
// ),
) {
MovingImageWall()
val context = LocalContext.current // 获取 Context
MovingImageWall(context.resources) // 将 resources 传递给 MovingImageWall
// MovingImageWall()
}
Column(
modifier = Modifier
@@ -233,14 +242,18 @@ fun LoginPage() {
@Composable
fun MovingImageWall() {
val imageList1 = remember { mutableStateListOf(R.drawable.wall_1_1, R.drawable.wall_1_2, R.drawable.wall_1_3) }
val imageList2 = remember { mutableStateListOf(R.drawable.wall_2_1, R.drawable.wall_2_2, R.drawable.wall_2_3) }
val imageList3 = remember { mutableStateListOf(R.drawable.wall_3_1, R.drawable.wall_3_2, R.drawable.wall_3_3) }
fun MovingImageWall(resources: Resources) {
val imageList1 = remember { mutableStateListOf(R.drawable.wall_1_1, R.drawable.wall_1_2, R.drawable.wall_1_3,R.drawable.wall_1_1, R.drawable.wall_1_2, R.drawable.wall_1_3) }
val imageList2 = remember { mutableStateListOf(R.drawable.wall_2_1, R.drawable.wall_2_2, R.drawable.wall_2_3,R.drawable.wall_2_1, R.drawable.wall_2_2, R.drawable.wall_2_3) }
val imageList3 = remember { mutableStateListOf(R.drawable.wall_3_1, R.drawable.wall_3_2, R.drawable.wall_3_3,R.drawable.wall_3_1, R.drawable.wall_3_2, R.drawable.wall_3_3) }
var offset1 by remember { mutableFloatStateOf(0f) }
val density = resources.displayMetrics.density // 获取屏幕密度
val imageHeight = 208.dp
val imageHeightPx = imageHeight.value * density // 将 dp 转换为像素
val resetThreshold = imageHeightPx
var offset1 by remember { mutableFloatStateOf( -resetThreshold * 3) }
var offset2 by remember { mutableFloatStateOf(0f) }
var offset3 by remember { mutableFloatStateOf(0f) }
var offset3 by remember { mutableFloatStateOf( -resetThreshold * 3) }
val lifecycleOwner = LocalLifecycleOwner.current
val coroutineScope = rememberCoroutineScope() // 使用 rememberCoroutineScope
@@ -250,13 +263,13 @@ fun MovingImageWall() {
when (event) {
Lifecycle.Event.ON_RESUME -> {
coroutineScope.launch { // 在 coroutineScope 中启动协程
animateImageWall(imageList1, offset1, speed = 1f) { offset1 = it }
animateImageWall(imageList1, offset1, speed = 1f, resources = resources) { offset1 = it }
}
coroutineScope.launch {
animateImageWall(imageList2, offset2, speed = 1.5f, reverse = true) { offset2 = it }
animateImageWall(imageList2, offset2, speed = 1.5f, reverse = true, resources = resources) { offset2 = it }
}
coroutineScope.launch {
animateImageWall(imageList3, offset3, speed = 2f) { offset3 = it }
animateImageWall(imageList3, offset3, speed = 2f, resources = resources) { offset3 = it }
}
}
Lifecycle.Event.ON_PAUSE -> {
@@ -271,27 +284,53 @@ fun MovingImageWall() {
Box(
modifier = Modifier
.fillMaxSize()
.offset(y = (-72).dp)
) {
Row (modifier = Modifier
.fillMaxWidth()
.height(700.dp)){
// .height(5000.dp)
// .offset(y = (-72).dp)
) {
val scrollState1 = rememberScrollState()
val scrollableState1 = rememberScrollableState { delta ->
// 消耗所有滚动事件,阻止用户滚动
delta
}
val scrollState2 = rememberScrollState()
val scrollableState2 = rememberScrollableState { delta ->
// 消耗所有滚动事件,阻止用户滚动
delta
}
val scrollState3 = rememberScrollState()
val scrollableState3 = rememberScrollableState { delta ->
// 消耗所有滚动事件,阻止用户滚动
delta
}
Row (modifier = Modifier
.fillMaxWidth()){
// 第1列
ImageColumn(imageList1, offset1,
Modifier
.fillMaxHeight()
.verticalScroll(scrollState1)
.scrollable(
state = scrollableState1,
orientation = Orientation.Vertical
)
.weight(1f))
// 第2列
ImageColumn(imageList2, offset2,
Modifier
.fillMaxHeight()
.verticalScroll(scrollState2)
.scrollable(
state = scrollableState2,
orientation = Orientation.Vertical
)
.weight(1f), reverse = true)
// 第3列
ImageColumn(imageList3, offset3,
Modifier
.fillMaxHeight()
.verticalScroll(scrollState3)
.scrollable(
state = scrollableState3,
orientation = Orientation.Vertical
)
.weight(1f))
}
@@ -346,11 +385,11 @@ fun ImageColumn(
offset
}
// 检查是否超出屏幕范围
if (translation < -imageHeight.value) { // 移出屏幕底部
translation += totalHeight
} else if (translation > totalHeight) { // 移出屏幕顶部
translation -= totalHeight
}
// if (translation < -imageHeight.value * 3) { // 移出屏幕底部
//// translation += (imageHeight.value * 3)
// } else if (translation > (totalHeight / 2)) { // 移出屏幕顶部
// translation -= (totalHeight / 2)
// }
translationY = translation
}
.clip(RoundedCornerShape(16.dp)),
@@ -370,68 +409,43 @@ fun ImageColumn(
}
}
}
suspend fun animateImageWall(
imageList: MutableList<Int>,
initialOffset: Float,
speed: Float,
speed: Float, // speed 现在以像素为单位
reverse: Boolean = false,
resources: Resources, // 添加 resources 参数
onUpdate: (Float) -> Unit,
) {
val density = resources.displayMetrics.density // 获取屏幕密度
var currentOffset = initialOffset
val imageCount = imageList.size
val imageHeight = 208.dp
var currentIndex = 0 // 添加一个变量来跟踪当前显示的图片索引
val imageHeightPx = imageHeight.value * density // 将 dp 转换为像素
val resetThreshold = imageHeightPx
Log.d(TAG, "speed: $speed")
Log.d(TAG, "resetThreshold: $resetThreshold")
while (true) {
onUpdate(currentOffset)
if (reverse) {
currentOffset -= speed
if (currentOffset < -imageHeight.value * (imageCount - 1)) {
// val firstImage = imageList.first() // 将第一个元素移除
// imageList.add(firstImage) // 将第一个元素添加到末尾
currentOffset += imageHeight.value * imageCount // 将图片移动到末尾
// currentIndex = (currentIndex - 1 + imageCount) % imageCount // 反向旋转
// Log.d(TAG, "currentOffset: $currentOffset")
if (currentOffset <= -resetThreshold * 3) { // 检查是否向上超出阈值
// 使用 imageHeightPx 进行计算
// 复位
currentOffset = initialOffset
}
} else {
currentOffset += speed
if (currentOffset > imageHeight.value * (imageCount - 1)) {
// val lastImage = imageList.last() // 将最后一个元素移除
// imageList.add(0, lastImage) // 将最后一个元素添加到开头
currentOffset -= imageHeight.value * imageCount // 将图片移动到开头
// currentIndex = (currentIndex + 1) % imageCount // 正向旋转
if (currentOffset >= 0) { // 检查是否向上超出阈值
Log.d(TAG, "currentOffset: $currentOffset")
// 使用 imageHeightPx 进行计算
// 复位
currentOffset = initialOffset
}
// 使用 imageHeightPx 进行计算
}
// 更新 ImageColumn 中的 currentImage
// onUpdate(currentIndex.toFloat()) // 将当前索引传递给 onUpdate
delay(16)
}
}
// 计算图片的透明度
private fun calculateAlpha(
offset: Float,
index: Int,
imageHeight: Float,
totalHeight: Float,
reverse: Boolean
): Float {
val offsetDp = if (reverse) {
-offset
} else {
offset
}
val imageTop = index * imageHeight
val imageBottom = imageTop + imageHeight
return when {
offsetDp in imageTop..imageBottom -> {
(offsetDp - imageTop) / imageHeight
}
(offsetDp + totalHeight) in imageTop..imageBottom -> { // 考虑循环滚动的情况
(offsetDp + totalHeight - imageTop) / imageHeight
}
(offsetDp - totalHeight) in imageTop..imageBottom -> { // 考虑循环滚动的情况
(offsetDp - totalHeight - imageTop) / imageHeight
}
else -> 0f
}
}