如何在Compose中优化AndroidView与懒惰列表的布局组合

发布于 2025-02-09 16:07:51 字数 4302 浏览 2 评论 0原文

我有两个问题,浏览lazycolumnverticalpager androidview填充整个屏幕,因为屏幕上的项目滞后于屏幕和滚动行为。几毫秒以及重叠的物品。在我的代码中androidView创建Playerview,我还尝试用playerview textview来检查可能问题。与Playerview本身。我似乎无法完全找到问题的根源,也许使用androidView或实现verticalpager本身,还是因为它填充了整个屏幕?

viewScreen

@OptIn(ExperimentalPagerApi::class)
@Composable
fun VideoScreen() {
    val pagerState = rememberPagerState()
    Box {
        VerticalPager(
            count = videos.size,
            state = pagerState,
            horizontalAlignment = Alignment.CenterHorizontally,
            itemSpacing = 10.dp
        ) { index ->

            VideoPlayer(
                vid = videos[index],
                shouldPlay = false
            )
        }
    }
}

videoplayer

@Composable
fun VideoPlayer(
    vid: Video,
    shouldPlay: Boolean
) {
    val exoPlayer = rememberExoPlayerWithLifecycle(vid.url)
    val playerView = rememberPlayerView(exoPlayer)

        AndroidView(
            factory = { playerView },
            modifier = Modifier,
            update = {
                exoPlayer.playWhenReady = shouldPlay
            }
        )

    DisposableEffect(key1 = true) {
        onDispose {
            exoPlayer.release()
        }
    }
}

rememberexoplayerwithlifecycle

@Composable
fun rememberExoPlayerWithLifecycle(
    url: String
): ExoPlayer {

    val context = LocalContext.current
    val exoPlayer = remember(url) {
        ExoPlayer.Builder(context).build().apply {
            videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT
            repeatMode = Player.REPEAT_MODE_ONE
            setHandleAudioBecomingNoisy(true)
            val defaultDataSource = DefaultHttpDataSource.Factory()
            val source = ProgressiveMediaSource.Factory(defaultDataSource)
                .createMediaSource(MediaItem.fromUri(url))
            setMediaSource(source)
            prepare()
        }
    }
    var appInBackground by remember {
        mutableStateOf(false)
    }
    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(key1 = lifecycleOwner, appInBackground) {
        val lifecycleObserver = getExoPlayerLifecycleObserver(exoPlayer, appInBackground) {
            appInBackground = it
        }
        lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(lifecycleObserver)
        }
    }
    return exoPlayer
}

记住playplayerview

@Composable
fun rememberPlayerView(exoPlayer: ExoPlayer): PlayerView {
    val context = LocalContext.current
    val playerView = remember {
        PlayerView(context).apply {
            layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
            useController = false
            resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
            player = exoPlayer
            setShowBuffering(SHOW_BUFFERING_ALWAYS)
        }
    }
    DisposableEffect(key1 = true) {
        onDispose {
            playerView.player = null
        }
    }
    return playerView
}

build> build.gradle.gradle(project)

buildscript {
ext {
    compose_version = '1.3.0-beta01'
   }
}
plugins {
    ...
    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
...

build。 gradle(模块)

...
dependencies {
    ...

    //Pager
    implementation "com.google.accompanist:accompanist-pager:0.26.2-beta"

    //Media 3
    def mediaVersion = "1.0.0-beta02"
    implementation "androidx.media3:media3-exoplayer:$mediaVersion"
    implementation "androidx.media3:media3-ui:$mediaVersion"

    ...
}

重叠项目

“一个”

I have got two problems, scrolling through LazyColumn or VerticalPager with AndroidView filling the whole screen as a child item lags the screen and the scrolling behavior for a couple of milliseconds as well as overlapping items. In my code the AndroidView creates PlayerView, I also tried to replace PlayerView with a TextView to check maybe the problem is with PlayerView itself. I can't seem to find the root of the problem exactly, maybe with the AndroidView or the implementation of the VerticalPager itself, or maybe because it fills the whole screen?

ViewScreen

@OptIn(ExperimentalPagerApi::class)
@Composable
fun VideoScreen() {
    val pagerState = rememberPagerState()
    Box {
        VerticalPager(
            count = videos.size,
            state = pagerState,
            horizontalAlignment = Alignment.CenterHorizontally,
            itemSpacing = 10.dp
        ) { index ->

            VideoPlayer(
                vid = videos[index],
                shouldPlay = false
            )
        }
    }
}

VideoPlayer

@Composable
fun VideoPlayer(
    vid: Video,
    shouldPlay: Boolean
) {
    val exoPlayer = rememberExoPlayerWithLifecycle(vid.url)
    val playerView = rememberPlayerView(exoPlayer)

        AndroidView(
            factory = { playerView },
            modifier = Modifier,
            update = {
                exoPlayer.playWhenReady = shouldPlay
            }
        )

    DisposableEffect(key1 = true) {
        onDispose {
            exoPlayer.release()
        }
    }
}

rememberExoPlayerWithLifecycle

@Composable
fun rememberExoPlayerWithLifecycle(
    url: String
): ExoPlayer {

    val context = LocalContext.current
    val exoPlayer = remember(url) {
        ExoPlayer.Builder(context).build().apply {
            videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT
            repeatMode = Player.REPEAT_MODE_ONE
            setHandleAudioBecomingNoisy(true)
            val defaultDataSource = DefaultHttpDataSource.Factory()
            val source = ProgressiveMediaSource.Factory(defaultDataSource)
                .createMediaSource(MediaItem.fromUri(url))
            setMediaSource(source)
            prepare()
        }
    }
    var appInBackground by remember {
        mutableStateOf(false)
    }
    val lifecycleOwner = LocalLifecycleOwner.current
    DisposableEffect(key1 = lifecycleOwner, appInBackground) {
        val lifecycleObserver = getExoPlayerLifecycleObserver(exoPlayer, appInBackground) {
            appInBackground = it
        }
        lifecycleOwner.lifecycle.addObserver(lifecycleObserver)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(lifecycleObserver)
        }
    }
    return exoPlayer
}

rememberPlayerView

@Composable
fun rememberPlayerView(exoPlayer: ExoPlayer): PlayerView {
    val context = LocalContext.current
    val playerView = remember {
        PlayerView(context).apply {
            layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
            useController = false
            resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
            player = exoPlayer
            setShowBuffering(SHOW_BUFFERING_ALWAYS)
        }
    }
    DisposableEffect(key1 = true) {
        onDispose {
            playerView.player = null
        }
    }
    return playerView
}

build.gradle (Project)

buildscript {
ext {
    compose_version = '1.3.0-beta01'
   }
}
plugins {
    ...
    id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
}
...

build.gradle (Module)

...
dependencies {
    ...

    //Pager
    implementation "com.google.accompanist:accompanist-pager:0.26.2-beta"

    //Media 3
    def mediaVersion = "1.0.0-beta02"
    implementation "androidx.media3:media3-exoplayer:$mediaVersion"
    implementation "androidx.media3:media3-ui:$mediaVersion"

    ...
}

Overlapping Items

one
two

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

海拔太高太耀眼 2025-02-16 16:07:52

使用expactratioframelayout.resize_mode_fit

Use AspectRatioFrameLayout.RESIZE_MODE_FIT

垂暮老矣 2025-02-16 16:07:52

我遇到了同样的问题,并将垂直码器更新为0.25.1外部词汇到2.18.1,并使用了StyledPlayerview而不是Playerview,并且似乎在起作用。

I was having the same issue and update verticalpager to 0.25.1 exoplater to 2.18.1 and used a StyledPlayerView instead of PlayerView and it seems to be working.

烂人 2025-02-16 16:07:52

而不是将

resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM

其替换为

resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
player.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING

instead of using

resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM

replace it with

resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT
player.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文