Видео -контент одного экзоплалриста, показанного в другом экзоплайере [дублировать]Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Видео -контент одного экзоплалриста, показанного в другом экзоплайере [дублировать]

Сообщение Anonymous »

Я работаю над приложением, подобным Twitter, используя JetPack Compose и Exoplayer3. В моем приложении Android есть сетка, состоящий из элементов сетки, которые могут быть видео или изображением. В следующей сетке из 3 предметов. Первый и третий - видео. Ориентация 2 -го видео является портретом, и оно переполняется от границы своего родительского контейнера в первое видео. Я обнаружил, что это происходит только тогда, когда два экзоплареи перекрывают друг друга. В следующей сетке 4 -й пункт также является портретным видео. Элемент выше - это изображение, а видео -белоты он остается в своем контейнере.@Composable
fun MediaPreviewGrid(
mediaItems: List,
viewModel: TweetViewModel,
onFullScreenVideo: ((String, MimeiId) -> Unit)? = null, // Callback for full-screen video
) {
val tweet by viewModel.tweetState.collectAsState()
val navController = LocalNavController.current
val maxItems = when (mediaItems.size) {
1 -> 1
2, 3 -> mediaItems.size
else -> 4
}

// Set up sequential playback for multiple videos
val videoMids = remember {
limitedMediaList.mapIndexedNotNull { index, item ->
if (inferMediaTypeFromAttachment(item) == MediaType.Video) item.mid else null
}
}

Box(
modifier = Modifier
.fillMaxWidth()
.wrapContentWidth(Alignment.CenterHorizontally)
) {
when (limitedMediaList.size) {
1 -> {
val aspectRatio = if (aspectRatioOf(limitedMediaList[0]) > 0.8f) {
aspectRatioOf(limitedMediaList[0])
} else {
0.8f
}
MediaItemView(
limitedMediaList,
modifier = Modifier
.fillMaxWidth()
.aspectRatio(aspectRatio)
.clipToBounds()
.clickable {
val params = MediaViewerParams(
mediaItems.map {
MediaItem(
getMediaUrl(it.mid, tweet.author?.baseUrl.orEmpty()).toString(),
it.type
)
}, 0, tweet.mid, tweet.authorId
)
navController.navigate(NavTweet.MediaViewer(params))
},
index = 0,
numOfHiddenItems = if (mediaItems.size > maxItems) mediaItems.size - maxItems else 0,
autoPlay = firstVideoIndex == 0,
inPreviewGrid = true,
viewModel = viewModel,
onFullScreenVideo = onFullScreenVideo
)
}
2 -> {}
3 -> {}
4 -> {}
}
}
}

@Composable
fun MediaItemView(
mediaItems: List,
modifier: Modifier = Modifier,
index: Int,
numOfHiddenItems: Int = 0, // add a PLUS sign to indicate more items not shown
autoPlay: Boolean = false, // autoplay first video item, index 0
inPreviewGrid: Boolean = true, // use real aspectRatio when not displaying in preview grid.
viewModel: TweetViewModel,
onFullScreenVideo: ((String, MimeiId) -> Unit)? = null // Callback for full-screen video
) {
val tweet by viewModel.tweetState.collectAsState()
val attachments = mediaItems.map {
val inferredType = inferMediaTypeFromAttachment(it)
val mediaUrl = getMediaUrl(it.mid, tweet.author?.baseUrl.orEmpty()).toString()
MediaItem(mediaUrl, inferredType)
}
val attachment = attachments[index]
val navController = LocalNavController.current

Box(
modifier = modifier
.background(Color.Gray.copy(alpha = 0.1f))
.clipToBounds(),
contentAlignment = Alignment.Center
) {
when (attachment.type) {
MediaType.Image -> {
// Use a Box with clickable modifier to handle image clicks
Box(
modifier = modifier
.clipToBounds()
.clickable {
goto(index)
}
) {
ImageViewer(
attachment.url,
modifier = Modifier.fillMaxSize(),
enableLongPress = false // Disable long press to allow clickable to work
)
}
}
MediaType.Video -> {
VideoPreview(
url = attachment.url,
modifier = modifier,
index = index,
autoPlay = autoPlay,
inPreviewGrid = inPreviewGrid,
aspectRatio = mediaItems[index].aspectRatio,
callback = { goto(index) },
videoMid = mediaItems[index].mid
)
}
MediaType.Audio -> {
val backgroundModifier = if (index % 2 != 0) { // Check if index is odd
modifier.background(Color.Black.copy(alpha = 0.05f)) // Slightly darker background
} else {
modifier
}
Box(
modifier = backgroundModifier
.clipToBounds()
.clickable {
goto(index)
}
) {
AudioPreview(mediaItems, index, Modifier.fillMaxSize(), tweet)
}
}
else -> { // add link to download other file type
BlobLink(mediaItems[index], attachment.url, modifier)
}
}
if (numOfHiddenItems > 0) {
/**
* Show a PLUS sign and number to indicate more items not shown
* */
Box(
modifier = Modifier
.matchParentSize()
.background(Color(0x40FFFFFF)), // Lighter shaded background
contentAlignment = Alignment.Center
) {
Row(modifier = Modifier.align(Alignment.Center))
{
Icon(
imageVector = Icons.Outlined.Add,
contentDescription = null,
tint = Color.White,
modifier = Modifier
.size(50.dp)
.alpha(0.8f)
)
Text(
text = numOfHiddenItems.toString(),
color = Color.White,
fontSize = 50.sp, // Adjust this value as needed
textAlign = TextAlign.Center,
modifier = Modifier
.alpha(0.8f)
)
}
}
}
}
}

@Composable
fun VideoPreview(
url: String,
modifier: Modifier,
index: Int,
autoPlay: Boolean = false,
inPreviewGrid: Boolean = true,
aspectRatio: Float?,
callback: (Int) -> Unit,
videoMid: MimeiId? = null
) {
val context = LocalContext.current
var isVideoVisible by remember { mutableStateOf(false) }
var isMuted by remember { mutableStateOf(preferenceHelper.getSpeakerMute()) }
var isLoading by remember {
mutableStateOf(videoMid?.let { !VideoManager.isVideoPreloaded(it) } ?: true)
}

val exoPlayer = remember(url, videoMid) {
if (videoMid != null) {
VideoManager.getVideoPlayer(context, videoMid, url)
} else {
createExoPlayer(context, url, MediaType.Video)
}
}

// Preload video if not already cached

Box(
modifier = modifier
.clipToBounds()
.background(MaterialTheme.colorScheme.surfaceVariant) // Material3 surface variant for loading background
.onGloballyPositioned { layoutCoordinates ->
isVideoVisible = isElementVisible(layoutCoordinates)
}
.clickable {
// Auto-start video in full screen
callback(index)
}
) {
AndroidView(
factory = {
PlayerView(context).apply {
player = exoPlayer
useController = false // No controls in preview mode
resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM
// Set background color to light gray (Material3 surface variant equivalent)
setBackgroundColor(android.graphics.Color.rgb(245, 245, 245))
// Show buffering indicator
setShowBuffering(PlayerView.SHOW_BUFFERING_ALWAYS)
}
},
modifier = Modifier.fillMaxWidth()
)

// Show loading indicator when video is loading
if (isLoading) {
Box(
modifier = Modifier
.fillMaxSize()
.background(MaterialTheme.colorScheme.surfaceVariant),
contentAlignment = androidx.compose.ui.Alignment.Center
) {
CircularProgressIndicator(
modifier = Modifier.size(32.dp),
color = MaterialTheme.colorScheme.primary
)
}
}
}
}


Подробнее здесь: https://stackoverflow.com/questions/794 ... -exoplayer
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»