I have an Activity that shows a video using VideoView with a custom MediaController. The system UI is hidden until the user taps the screen to show the MediaController (just like in YouTube or Photos app).
The following method takes care of hiding the system 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);
}
And the layout of the 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>
I then add the MediaController to video_frame
via code like so:
mMediaController.setAnchorView(findViewById(R.id.video_frame));
Testing with Nexus 5, I noticed that when showing the MediaController, the soft navigation bar is overlapping the MediaController UI. I managed to fix it by adding the following attribute to the root of MediaController layout:
android:fitsSystemWindows="true"
So far so good. This worked perfectly fine as long as my Activity theme was Theme.AppCompat.NoActionBar
. Now that I'm refactoring the app, getting it as per Material design guidelines for featuring, I have to show the ActionBar.
So I changed the theme to Theme.AppCompat
and guess what? The system UI once again overlaps the MediaController. It seems that android:fitsSystemWindows="true"
has absolutely no affect anymore.
I've tried to set android:fitsSystemWindows="true"
directly to the Activity theme itself and it seemed to solve the overlapping issue, but then I got another issue where the VideoView was padded in a totally weird way from random direction, instead of scaling to fit the screen as it used to be.
I've spent hours on that and still can't figure out a clean solution. Please note that I need a solution that works for Tablets and Phones together. And as you probably know, on tablets, the soft navigation bar appears at the bottom of the screen while in landscape mode. I prefer to solve the issue via XML if possible.
After examining Android Studio's Fullscreen Activity template, I noticed that in the FullscreenActivity layout they are using android:fitsSystemWindows="true"
in a little bit different way than me.
Here's the layout that comes with the template (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>
I noticed that they have an additional FrameLayout
container set with android:fitsSystemWindows="true"
that wraps the actual layout container (in my case this was the MediaController
) at the bottom of the screen.
Once I added a FrameLayout
to wrap my MediaController
layout as shown in the above code snippet my problem is gone! Really weird that I need to have additional layout container to solve this issue. Especially when Android Studio is saying now that I have "Useless Parent".
So to summarize, here is the fully working solution of how my Activity layout looks like:
<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>
and I hook up the MediaController
to controller_frame
instead of video_frame
as I did previously:
mMediaController.setAnchorView(findViewById(R.id.controller_frame));