feat: add DogParkScreen for full-screen easter egg video

This commit is contained in:
xfy 2026-06-16 16:06:01 +08:00
parent 9d2f67b9fb
commit 6532363cdb

View File

@ -0,0 +1,92 @@
package plus.rua.project.ui
import android.view.ViewGroup
import android.widget.FrameLayout
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.media3.common.MediaItem
import androidx.media3.common.Player
import androidx.media3.common.PlaybackException
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.AspectRatioFrameLayout
import androidx.media3.ui.PlayerView
/**
* 小狗乐园彩蛋页面全屏循环播放彩蛋视频
*
* 特性
* - 视频源`asset:///video/enter_screen_bg1.mp4`
* - 等比裁剪铺满全屏`RESIZE_MODE_ZOOM`
* - 静音无播放控件循环播放
* - 跟随生命周期自动 play / pause离开页面时自动释放
*
* @param onPlaybackError 播放出错时的回调通常由调用方 finish Activity
* @param modifier 布局修饰符
*/
@Composable
fun DogParkScreen(
onPlaybackError: () -> Unit,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
val lifecycleOwner = LocalLifecycleOwner.current
val player = remember(context) {
ExoPlayer.Builder(context).build().apply {
volume = 0f
repeatMode = Player.REPEAT_MODE_ONE
setMediaItem(MediaItem.fromUri("asset:///video/enter_screen_bg1.mp4"))
addListener(object : Player.Listener {
override fun onPlayerError(error: PlaybackException) {
onPlaybackError()
}
})
prepare()
if (lifecycleOwner.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
play()
}
}
}
DisposableEffect(player, lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_RESUME -> player.play()
Lifecycle.Event.ON_PAUSE -> player.pause()
else -> Unit
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
player.release()
}
}
AndroidView(
factory = { ctx ->
PlayerView(ctx).apply {
layoutParams = FrameLayout.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
useController = false
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
}
},
update = { playerView ->
if (playerView.player != player) {
playerView.player = player
}
},
modifier = modifier.fillMaxSize()
)
}