视频暂停并播放时视频会重复 exoplayer 3 jetpack compose

问题描述 投票:0回答:1

我使用LaunchedEffect和while来按时获取currentTime,但是当我按下暂停和播放按钮时,视频会重复

PlayerScreen.kt

@OptIn(UnstableApi::class)
@Composable
fun PlayerScreen(
    navController: NavHostController,
    modifier: Modifier = Modifier
) {
    val videoUrl = "http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"
    val context = LocalContext.current
    val player = remember { ExoPlayer.Builder(context).build() }
    val playerView = remember { PlayerView(context) }
    val mediaItem = remember { MediaItem.fromUri(videoUrl) }
    var isPlaying by rememberSaveable { mutableStateOf(true) }
    player.setMediaItem(mediaItem)
    playerView.player = player
    LaunchedEffect(player){
        player.prepare()
        player.playWhenReady = isPlaying
    }
    var currentTime by remember { mutableLongStateOf(1L) }
    var maxDuration by remember { mutableLongStateOf(50L) }
    if (isPlaying) {
        LaunchedEffect(isPlaying) { // Menggunakan isPlaying sebagai dependencies
            while(true) {    
                currentTime = player.currentPosition
                if(player.isPlaying){
                    maxDuration = player.duration
                }
                delay(1.seconds / 30)
            }
        }
    }
    DisposableEffect(player) {
        onDispose {
            player.release()
        }
    }
    Box(modifier = modifier) {
        AndroidView(factory = {
            playerView.apply {
//                resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
                useController = false
                layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
            }
        })

        ControllerPlayer(
            isPlaying = { isPlaying },
            onReplayClick = { player.seekBack() },
            onPauseToggle = {
                if (player.isPlaying) {
                    player.pause()
                } else {
                    player.play()
                }
                isPlaying = isPlaying.not()
            },
            onForwardClick = { player.seekForward() },
            totalDuration = { maxDuration },
            currentTime = { currentTime },
            bufferPercentage = { player.bufferedPercentage },
            onSeekChanged = { newPosition ->
                player.seekTo(newPosition.toLong())
            },
            isVisibleController = {true}
        )
    }
}

我不认为代码有问题,但我还是给你代码 ControllerScreen.kt

@SuppressLint("RememberReturnType")
@OptIn(UnstableApi::class)
@Composable
fun BoxScope.ControllerPlayer(
    modifier: Modifier = Modifier,
    isPlaying: () -> Boolean,
    onReplayClick: () -> Unit,
    onPauseToggle: () -> Unit,
    onForwardClick: () -> Unit,
    totalDuration: () -> Long,
    currentTime: () -> Long,
    bufferPercentage: () -> Int,
    onSeekChanged: (timeMs: Float) -> Unit,
    isVisibleController: () -> Boolean,
) {
    val isVideoPlaying = remember(isPlaying()) { isPlaying() }
    val visible = remember(isVisibleController()) { isVisibleController() }
    val duration = remember(totalDuration()) { totalDuration() }
    val videoTime = remember(currentTime()) { currentTime() }
    val buffer = remember(bufferPercentage()) { bufferPercentage() }
    AnimatedVisibility(
        visible = if(AppConfig.isProduction()) visible else true,
        enter = fadeIn(tween(200)),
        exit = fadeOut(tween(200))
    ) {
        Box(modifier = modifier.fillMaxSize()){
            Row(
                modifier = modifier
                    .align(Alignment.Center),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                IconButton(modifier = Modifier.size(40.dp), onClick = onReplayClick) {
                    Image(
                        modifier = Modifier.fillMaxSize(),
                        contentScale = ContentScale.Crop,
                        painter = painterResource(id = androidx.media3.ui.R.drawable.exo_ic_chevron_left),
                        contentDescription = "Replay 5 seconds"
                    )
                }

                IconButton(modifier = Modifier.size(40.dp), onClick = onPauseToggle) {
                    Image(
                        modifier = Modifier.fillMaxSize(),
                        contentScale = ContentScale.Crop,
                        painter =
                        if (isVideoPlaying) {
                            painterResource(id = androidx.media3.ui.R.drawable.exo_icon_pause)
                        } else {
                            painterResource(id = androidx.media3.ui.R.drawable.exo_icon_play)
                        },
                        contentDescription = "Play/Pause"
                    )
                }

                IconButton(modifier = Modifier.size(40.dp), onClick = onForwardClick) {
                    Image(
                        modifier = Modifier.fillMaxSize(),
                        contentScale = ContentScale.Crop,
                        painter = painterResource(id = androidx.media3.ui.R.drawable.exo_ic_chevron_right),
                        contentDescription = "Forward 10 seconds"
                    )
                }
            }

            Column(
                modifier = modifier
                    .align(Alignment.BottomCenter)
                    .padding(bottom = 32.dp)
            ) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 16.dp),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.Bottom
                ) {
                    Text(
                        modifier = Modifier.padding(horizontal = 16.dp),
                        text = "${videoTime.formatMinSec()} / ${duration.formatMinSec()}",
                        color = DarkTheme.onSecondary
                    )

                    IconButton(
                        modifier = Modifier.padding(horizontal = 16.dp),
                        onClick = {}
                    ) {
                        Image(
                            contentScale = ContentScale.Crop,
                            painter = painterResource(id = androidx.media3.ui.R.drawable.exo_icon_fullscreen_enter),
                            contentDescription = "Enter/Exit fullscreen"
                        )
                    }
                }
                Box(modifier = Modifier.fillMaxWidth()) {
                    // buffer bar
                    Slider(
                        value = buffer.toFloat(),
                        enabled = false,
                        onValueChange = { /*do nothing*/ },
                        valueRange = 0f..100f,
                        colors =
                        SliderDefaults.colors(
                            disabledThumbColor = Color.Transparent,
                            disabledActiveTrackColor = Color.Gray
                        )
                    )

                    // seek bar
                    Slider(
                        modifier = Modifier.fillMaxWidth(),
                        value = videoTime.toFloat(),
                        onValueChange = onSeekChanged,
                        valueRange = 0f..duration.toFloat(),
                        colors =
                        SliderDefaults.colors(
                            thumbColor = DarkTheme.tertiary,
                            activeTickColor = DarkTheme.onSecondary
                        )
                    )
                }
            }
        }
    }
}

fun Long.formatMinSec(): String {
    return if (this == 0L) {
        "..."
    } else {
        String.format(
            "%02d:%02d",
            TimeUnit.MILLISECONDS.toMinutes(this),
            TimeUnit.MILLISECONDS.toSeconds(this) -
                    TimeUnit.MINUTES.toSeconds(
                        TimeUnit.MILLISECONDS.toMinutes(this)
                    )
        )
    }
}

我希望如果我按下暂停按钮并播放视频就不会重复

android kotlin android-jetpack-compose exoplayer exoplayer2.x
1个回答
0
投票

我将你的代码运行到我的系统中,找到了一个解决方案。

当您单击暂停按钮时,您将切换 isPlaying 的值,但它也会影响其他地方。所以我只是创建其他变量,当单击暂停时,我只是更改其他变量的值,然后它工作完美。

只需创建另一个变量

var isVideoContinue by rememberSaveable { mutableStateOf(true) }

将此 isVideoContinue 变量放入 ControllerPlayer 中

ControllerPlayer(
            isPlaying = { isVideoContinue },
            onReplayClick = { player.seekBack() },
            onPauseToggle = {
                if (player.isPlaying) {
                    player.pause()
                } else {
                    player.play()
                }
                isVideoContinue = isVideoContinue.not()
            },
            onForwardClick = { player.seekForward() },
            totalDuration = { maxDuration },
            currentTime = { currentTime },
            bufferPercentage = { player.bufferedPercentage },
            onSeekChanged = { newPosition ->
                player.seekTo(newPosition.toLong())
            },
            isVisibleController = { true }
        )

player.playWhenReady = isPlaying

我不确定,但您在 playWhenReady 上使用 isPlaying,因此可能的原因是,每当单击暂停按钮时 isPlaying 变量发生变化,它就会重新启动视频。

© www.soinside.com 2019 - 2024. All rights reserved.