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