#android-layout #exoplayer2.x
#android-layout #exoplayer2.x
Вопрос:
Мое приложение использует настраиваемый FrameLayout, который содержит PlayerView и другой пользовательский FrameLayout («DrawView»). Цель состоит в том, чтобы нарисовать настраиваемые фигуры в FrameLayout, которые появляются поверх воспроизводимого видео.
В макете сначала у меня есть PlayerView, затем DrawView:
<!-- customized FrameLayout encompassing ViewPager2 and DrawView, which implements that capability of
detecting taps -->
<com.reddragon.intouch.utils.ViewPager2Host
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@ id/viewpager2host"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
tools:context=".ui.MediaPlayerActivity">
<androidx.viewpager2.widget.ViewPager2
android:id="@ id/activity_media_player_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.viewpager2.widget.ViewPager2>
<com.reddragon.intouch.ui.drawview.DrawView
android:id="@ id/drawView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
DrawView
Компонент используется для рисования фигур и текста поверх видео, поэтому мне нужно изменить его размер в соответствии с размером и положением прямоугольника, который представляет, где воспроизводится видео.
Для этого у меня правильно реализована логика, и я реализовал VideoListener и поместил эту логику внутри onSurfaceSizeChanged()
.
Это работает нормально — и, как вы можете видеть на скриншоте, красная линия (представляющая границы окружающего родительского ViewPager2Host) и зеленая линия (представляющие границы / расположение видеоповерхности, которые я рассчитал во время выполнения для этого конкретного видео) верны:
Вот мой вопрос — onSurfaceSizeChanged()
вызывается несколько раз, и я хочу выполнить вычисление размера и местоположения только один раз DrawView
. Из моего тестирования видно, что до тех пор, пока ViewPager2Host
родительский элемент не изменяет размеры, он onSurfaceSizeChanged()
вызывается дважды, а второй раз является «конечным» измерением.
Кто-нибудь может подтвердить, что это так? Или есть случаи — возможно, когда родительские размеры точно соответствуют размеру видеоповерхности, который onSurfaceSizeChanged()
будет вызываться только один раз?
Или есть какой-то способ узнать, когда размер поверхности является «окончательным»?
Я пытаюсь реализовать какую-то логику «если видео инициализируется, то», чтобы только ПОСЛЕ завершения всего макета и завершения прямой видеоповерхности я вычислял размер и размещение DrawView.
Ответ №1:
Кажется, что простой ответ на мой первоначальный вопрос: НЕТ — нет гарантии, сколько раз это вызывается в обычном конвейере рендеринга, за исключением того, что он вызывается хотя бы один раз.
При дальнейшем тестировании также становится ясно, что даже после вызова onPlayerStateChanged() с помощью STATE_READY размер видео еще не стабилен (я уже много раз видел, что onSurfaceSizeChanged() вызывается с обновленными значениями даже после вызова STATE_READY).
Итак, моя первоначальная идея обрабатывать все в onPlayerStateChanged() после того, как playWhenReady имеет значение TRUE, теперь не кажется хорошим ответом.
Все еще ищу, как я могу определить, что поверхность видео уменьшилась до размера, который, по его мнению, является «окончательным» для воспроизведения видео!
В качестве обновления мой настраиваемый FrameLayout имеет три «слоя» (каждый из которых полностью заполняет держатель, связанный с текущим адаптером ViewPager2):
- Отображение мультимедиа (либо реализация Glide для изображений, либо ExoPlayer2 PlayerView для мультимедиа)
- DrawView (настраиваемый FrameLayout, который содержит различные фигуры, нарисованные сверху)
- FrameLayout (содержит неопределенный индикатор выполнения и текст, отображаемый, когда для буферизации видеоматериалов из Интернета требуется некоторое время)
Мое решение закончилось тем, что (после того, как элемент «next» в ViewPager2 recyclerview был готов к отображению видео):
- Изначально скройте слои DrawView и Media Display
- Показать «загружаемые» компоненты
- Установите playerwhenready(true) на ExoPlayer
- подготовка (mediaDataSource)
- В обратном вызове onPlayerStateChanged() из ExoPlayer, который реализует моя activity, проверьте, что значение playWhenReady равно TRUE, а значение plabackState равно STATE_READY, а затем
- удалите «загрузочные» представления
- установите вид ExoPlayer видимым
- вычислите различные виджеты для рисования в DrawView с учетом размеров и положения videoSurfaceView ExoPlayer
- установите видимый вид.
Я не уверен почему, но, похоже, переопределение других обратных вызовов, таких как из VideoListener, не «подталкивало» представления к правильному рисованию. Я видел множество случаев, когда вызывалась onDraw() класса DrawView, но ни onDraw виджетов, ни onDispatchDraw класса DrawView не вызывались.