Android: настройка MediaController для соответствия системному интерфейсу не работает с панелью действий
У меня есть активность, которая показывает видео с использованием VideoView с пользовательским MediaController. Системный интерфейс скрыт до тех пор, пока пользователь не коснется экрана, чтобы отобразить MediaController (как в приложении YouTube или Фото).
Следующий метод позволяет скрыть системный интерфейс:
private void hideSystemUi() {
int flags = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
getWindow().getDecorView().setSystemUiVisibility(flags);
}
И макет деятельности:
<FrameLayout android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:keepScreenOn="true">
<com.google.android.exoplayer.AspectRatioFrameLayout
android:id="@+id/video_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
</com.google.android.exoplayer.AspectRatioFrameLayout>
</FrameLayout>
Затем я добавляю MediaController в video_frame
с помощью кода, например, так:
mMediaController.setAnchorView(findViewById(R.id.video_frame));
Тестируя с Nexus 5, я заметил, что при отображении MediaController программная панель навигации перекрывает пользовательский интерфейс MediaController. Мне удалось это исправить, добавив следующий атрибут в корень макета MediaController:
android:fitsSystemWindows="true"
Все идет нормально. Это работало отлично, пока моя тема была Theme.AppCompat.NoActionBar
, Теперь, когда я провожу рефакторинг приложения, получая его в соответствии с рекомендациями по дизайну материалов, я должен показать ActionBar. Поэтому я сменил тему на Theme.AppCompat
и угадай что? Системный интерфейс еще раз перекрывает MediaController. Кажется, что android:fitsSystemWindows="true"
больше не имеет никакого влияния.
Я пытался установить android:fitsSystemWindows="true"
непосредственно к самой теме "Активность", и это, казалось, решило проблему с перекрытием, но потом я получил еще одну проблему, когда VideoView был дополнен совершенно странным образом со случайного направления вместо масштабирования, чтобы соответствовать экрану, как это было раньше.
Я потратил на это часы и до сих пор не могу найти чистое решение.Обратите внимание, что мне нужно решение, которое работает для планшетов и телефонов вместе. И, как вы, наверное, знаете, на планшетах в нижней части экрана отображается мягкая навигационная панель в ландшафтном режиме. Я предпочитаю решить проблему через XML, если это возможно.
1 ответ
Изучив шаблон Fullscreen Activity в Android Studio, я заметил, что в макете FullscreenActivity они используют android:fitsSystemWindows="true"
немного по-другому, чем я.
Вот макет, который поставляется с шаблоном (activity_fullscreen.xml):
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0099cc"
tools:context=".FullscreenActivity">
<!-- The primary full-screen view. This can be replaced with whatever view
is needed to present your content, e.g. VideoView, SurfaceView,
TextureView, etc. -->
<TextView android:id="@+id/fullscreen_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
android:textColor="#33b5e5"
android:textStyle="bold"
android:textSize="50sp"
android:gravity="center"
android:text="@string/dummy_content"/>
<!-- This FrameLayout insets its children based on system windows using
android:fitsSystemWindows. -->
<FrameLayout android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout android:id="@+id/fullscreen_content_controls"
style="?metaButtonBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:background="@color/black_overlay"
android:orientation="horizontal"
tools:ignore="UselessParent">
<Button android:id="@+id/dummy_button"
style="?metaButtonBarButtonStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/dummy_button"/>
</LinearLayout>
</FrameLayout>
</FrameLayout>
Я заметил, что у них есть дополнительный FrameLayout
контейнер с android:fitsSystemWindows="true"
который оборачивает фактический контейнер макета (в моем случае это был MediaController
) внизу экрана.
Однажды я добавил FrameLayout
обернуть мой MediaController
макет, как показано в приведенном выше фрагменте кода, моя проблема исчезла! Действительно странно, что мне нужен дополнительный макет контейнера, чтобы решить эту проблему. Особенно, когда Android Studio говорит, что у меня есть "Бесполезный родитель".
Итак, подведем итог, вот полностью рабочее решение того, как выглядит мой макет Activity:
<FrameLayout android:id="@+id/root"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:keepScreenOn="true">
<com.google.android.exoplayer.AspectRatioFrameLayout
android:id="@+id/video_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<SurfaceView
android:id="@+id/surface_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"/>
</com.google.android.exoplayer.AspectRatioFrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<LinearLayout android:id="@+id/controller_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:orientation="horizontal">
</LinearLayout>
</FrameLayout>
</FrameLayout>
и я подключаю MediaController
в controller_frame
вместо video_frame
как я делал ранее:
mMediaController.setAnchorView(findViewById(R.id.controller_frame));