0

我有 2 个屏幕,里面有 videoview,我使用 accompanist-navigation-animation 库在它们之间进行转换。两个组成“屏幕”之间的转换很慢,我认为这可能与我如何开始视频有关,但我无法弄清楚。此外,当从第一个屏幕转换到第二个屏幕时,重新组合会运行多次。有更多知识的人可以看看我如何处理视频播放。

@ExperimentalAnimationApi
@Composable
fun Navigation() {
val navController = rememberAnimatedNavController()
val activity = (LocalContext.current as? Activity)

AnimatedNavHost(
    navController = navController,
    startDestination = "promoScreen1"
) {
    composable("promoScreen1",
        exitTransition = {
            slideOutOfContainer(
                AnimatedContentScope.SlideDirection.Left,
                animationSpec = tween(1000)
            )
        }
    ) {
        val repeatsPromoViewModel: RepeatsPromoViewModel = viewModel()
        RepeatsPromoScreen(
            repeatsPromoViewModel = viewModel(),
            navController = navController,
            videoFileName = "repeat_promo1",
            title = stringResource(id = R.string.repeats_promo_title1),
            subtitle = stringResource(id = R.string.repeats_promo_subtitle),
            description = stringResource(id = R.string.repeats_promo_description),
            bottomButtonText = stringResource(id = R.string.next).uppercase(),
            onBottomButtonClicked = {
                repeatsPromoViewModel._overlayVisible.value = true
                repeatsPromoViewModel.isPlaying.value = false
                navController.navigate("promoScreen2")
            }
        )
    }
    composable("promoScreen2", enterTransition = {
        slideIntoContainer(
            AnimatedContentScope.SlideDirection.Left,
            animationSpec = tween(1000)
        )
    }) {
        val repeatsPromoViewModel: RepeatsPromoViewModel = viewModel()

        BackHandler(true) {} //disable back button
        RepeatsPromoScreen(
            repeatsPromoViewModel = repeatsPromoViewModel,
            navController = navController,
            videoFileName = "repeat_promo2",
            title = stringResource(id = R.string.repeats_promo_title2),
            subtitle = stringResource(id = R.string.repeats_promo_subtitle2),
            description = stringResource(id = R.string.repeats_promo_description2),
            bottomButtonText = stringResource(id = R.string.planning_tutorial_finish).uppercase()
        ) { activity?.finish() }
    }
   }
 }

@ExperimentalAnimationApi
@Composable
fun RepeatsPromoScreen(
repeatsPromoViewModel: RepeatsPromoViewModel,
navController: NavController,
videoFileName: String,
title: String,
subtitle: String,
description: String,
bottomButtonText: String,
onBottomButtonClicked: () -> Unit
 ) {
val activity = (LocalContext.current as? Activity)
val overlayVisible by repeatsPromoViewModel.overlayVisible

val configuration = LocalConfiguration.current
val isSmallScreen = configuration.screenHeightDp < 720 || configuration.screenWidthDp <= 360

var modifier = Modifier
    .fillMaxSize()
    .background(color = Color(0xFFEBF4F9))

if (isSmallScreen) {
    modifier =
        modifier.then(Modifier.verticalScroll(rememberScrollState())) //enable scrolling on small screens
}

Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    modifier = modifier
) {

    Box(
        modifier = Modifier
            .fillMaxWidth()
            .align(Alignment.Start)
    ) {
        IconButton(
            onClick = { activity?.finish() }
        ) {
            Icon(
                Icons.Filled.Close,
                contentDescription = "Close screen"
            )
        }
    }

    Text(
        text = title,
        fontSize = 28.sp,
        lineHeight = 22.sp,
        textAlign = TextAlign.Center,
        fontFamily = FontFamily(Font(R.font.source_serif_pro_black)),
        modifier = Modifier.padding(top = 24.dp),
        color = colorResource(id = R.color.toshl_profile_name)
    )
    Text(
        text = subtitle,
        fontSize = 14.sp,
        lineHeight = 17.sp,
        textAlign = TextAlign.Center,
        modifier = Modifier.padding(top = 10.dp, start = 50.dp, end = 50.dp),
        color = colorResource(id = R.color.toshl_sync_subtitle)
    )

    val rawId =
        activity?.resources?.getIdentifier(videoFileName, "raw", activity.packageName)
    val path = "android.resource://" + activity?.packageName + "/" + rawId

    val retriever = MediaMetadataRetriever()
    retriever.setDataSource(activity, Uri.parse(path))
    val frame = retriever.frameAtTime

    val videoWidth = frame?.width?.toFloat() ?: 0.toFloat()
    val videoHeight = frame?.height?.toFloat() ?: 0.toFloat()

    val ratio = configuration.screenWidthDp / UiHelper.convertPxToDp(
        activity!!.applicationContext,
        videoWidth
    )

    val videoView = remember(activity) {
        VideoView(activity).apply {
            setVideoPath(path)
            setOnPreparedListener { mp: MediaPlayer ->
                mp.setOnInfoListener(MediaPlayer.OnInfoListener { mp, what, _ ->
                    if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
                        repeatsPromoViewModel._overlayVisible.value = false
                        return@OnInfoListener true
                    }
                    false
                })

                mp.start()
                mp.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING)
                mp.isLooping = true
            }
        }
    }

    val videoContainerHeight =
        UiHelper.convertPxToDp(activity.applicationContext, videoHeight) * ratio
    Box() {

        AndroidView(
            modifier = Modifier
                .padding(top = 25.dp, start = 0.dp, end = 0.dp)
                .height(videoContainerHeight.dp),
            factory = { context ->
                videoView
            }
        )
        //overlay
        this@Column.AnimatedVisibility(visible = overlayVisible) {
            Box(
                modifier = Modifier
                    .padding(top = 25.dp, start = 0.dp, end = 0.dp)
                    .height(videoContainerHeight.dp)
                    .background(Color(0xFFEBF4F9))
                    .clip(RectangleShape)
                    .fillMaxSize()
            )
        }
    }

    Text(
        text = description,
        fontSize = 14.sp,
        lineHeight = 17.sp,
        textAlign = TextAlign.Center,
        modifier = Modifier.padding(top = 30.dp, start = 50.dp, end = 50.dp),
        color = colorResource(id = R.color.toshl_sync_subtitle)
    )

    if (isSmallScreen) { //just add button below other elements
        PromoBottomButton(
            paddingTop = 32.dp,
            paddingBottom = 16.dp,
            onFinishClicked = { },
            text = stringResource(id = R.string.next).uppercase()
        )
    } else { //pin button to bottom of screen (that's why its wrapped inside another column)
        Column(
            modifier = Modifier
                .fillMaxSize()
                .align(Alignment.CenterHorizontally),
            verticalArrangement = Arrangement.Bottom
        ) {
            PromoBottomButton(
                paddingTop = 16.dp,
                paddingBottom = 32.dp,
                onFinishClicked = { onBottomButtonClicked.invoke() },
                text = bottomButtonText
            )
        }
    }
}

}

4

0 回答 0