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));
我有一个 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));