feat: add DogParkScreen for full-screen easter egg video
This commit is contained in:
parent
9d2f67b9fb
commit
6532363cdb
92
core/src/main/kotlin/plus/rua/project/ui/DogParkScreen.kt
Normal file
92
core/src/main/kotlin/plus/rua/project/ui/DogParkScreen.kt
Normal 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()
|
||||
)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user