I have a HorizontalPager which contains two pages and Two VideoPlayerView in each page.The problem is when I play one video and scroll to another page the another page video player shows the same video from other page instead showing it's own video. The video needs to be zoomed and croped fit the Height or full screen . I think video width is so large and it overflows since I am zooming to maintain ratio. Can we bound the video within one pager width??
Code for VideoPlayerView is
:
@OptIn(UnstableApi::class) @Composable
fun VideoPlayerView(
uri: String,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
val density = LocalDensity.current
var isReady by remember{ mutableStateOf(false) }
val screenWidth = LocalConfiguration.current.screenWidthDp
val screenHeight = LocalConfiguration.current.screenHeightDp
val model = ImageRequest.Builder(context)
.data(uri)
.videoFrameMillis(10000)
.decoderFactory { result, options, _ ->
VideoFrameDecoder(
result.source,
options
)
}
.build()
val exoPlayer = remember{ createExoPlayer(context, uri) }
//exoPlayer.playWhenReady = true
exoPlayer.videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING
exoPlayer.repeatMode = Player.REPEAT_MODE_ONE
exoPlayer.addListener(object : Player.Listener{
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
isReady = playWhenReady
super.onPlayWhenReadyChanged(playWhenReady, reason)
}
})
var lifecycle by remember { mutableStateOf(Lifecycle.Event.ON_CREATE) }
val lifecycleOwner = LocalLifecycleOwner.current
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
lifecycle = event
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
exoPlayer.release()
}
}
Box(
modifier = Modifier
//.widthIn(max = with(density) { screenWidth.toDp() })
// .width(200.dp)
// .fillMaxHeight()
//.height(200.dp)
.onGloballyPositioned { coordinates ->
val parentRect = coordinates.boundsInParent()
val isFullyVisible = parentRect.contains(coordinates.positionInWindow())
if (isFullyVisible) {
exoPlayer.play()
} else {
exoPlayer.pause()
}
},
contentAlignment = Alignment.Center
){
//if(!isReady){
if(exoPlayer.isLoading){
AsyncImage(
modifier = Modifier.fillMaxSize(),
model = model,
contentDescription = "video thumbnail",
contentScale = ContentScale.Crop
)
}else{
AndroidView(
factory = { context ->
val playerView = PlayerView(context).apply {
hideController()
useController = false
player = exoPlayer
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
setKeepContentOnPlayerReset(true)
}
playerView
},
update = {
when (lifecycle) {
Lifecycle.Event.ON_PAUSE -> {
it.onPause()
it.player?.pause()
}
Lifecycle.Event.ON_RESUME -> {
it.onResume()
}
else -> Unit
}
},
modifier = modifier
.fillMaxSize()
)
}
}
}
@OptIn(UnstableApi::class)
private fun createExoPlayer(context: Context, uri: String): ExoPlayer{
return ExoPlayer.Builder(context)
.build()
.apply {
val defaultDataSourceFactory = DefaultDataSource.Factory(context)
val dataSourceFactory: DataSource.Factory = DefaultDataSource.Factory(
context,
defaultDataSourceFactory
)
val source = ProgressiveMediaSource.Factory(dataSourceFactory)
.createMediaSource(MediaItem.fromUri(uri))
setMediaSource(source)
prepare()
}
}
On your
PlayerView
, addclipToOutline
as true.