首页动画完成
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user