Android:调整 MediaController 以适应系统 UI 不适用于 Action Bar

Android: Adjusting MediaController to fit system UI doesn't work with Action Bar

我有一个 Activity 显示使用 VideoView 和自定义 MediaController 的视频。系统 UI 一直隐藏,直到用户点击屏幕以显示 MediaController(就像在 YouTube 或照片应用中一样)。

以下方法负责隐藏系统 UI:

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);

}

以及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>

然后我通过如下代码将 MediaController 添加到 video_frame

mMediaController.setAnchorView(findViewById(R.id.video_frame));

使用 Nexus 5 进行测试时,我注意到在显示 MediaController 时,软导航栏与 MediaController 重叠 UI。我设法通过将以下属性添加到 MediaController 布局的根目录来修复它:

android:fitsSystemWindows="true"

到目前为止一切顺利。只要我的 Activity 主题是 Theme.AppCompat.NoActionBar,它就可以正常工作。现在我正在重构应用程序,根据 Material 设计指南进行特色设计,我必须显示 ActionBar。 所以我将主题更改为 Theme.AppCompat,你猜怎么着?系统 UI 再次与 MediaController 重叠。看来android:fitsSystemWindows="true"已经完全没有影响了。

我尝试将 android:fitsSystemWindows="true" 直接设置为 Activity 主题本身,这似乎解决了重叠问题,但后来我又遇到了另一个问题,其中 VideoView 被填充了从随机方向以一种完全奇怪的方式,而不是像以前那样缩放以适合屏幕。

我已经为此花费了几个小时,但仍然无法找到一个干净的解决方案。 请注意我需要一个同时适用于平板电脑和手机的解决方案。 您可能知道,在平板电脑上,软导航栏在横向模式下出现在屏幕底部。 如果可能,我更愿意通过 XML 解决问题。

在检查 Android Studio 的全屏 Activity 模板后,我注意到在全屏Activity 布局中,他们使用 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 现在说我有 "Useless Parent".

总而言之,这是我的 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));