I'm porting a codebase from native Holo (Theme.Holo
etc) to the appcompat-v7
(Theme.AppCompat
and so on). The last section contains the tl;dr if you don't want to read the details.
Everything's working but I had issues replicating one behaviour that was quite easy to have using the old ActionBar. I have a video player, and in landscape I want it to behave like YouTube: hide (animating) the player controls, app bar and status bar. On user interaction, the UI controls should leave this "lights out" mode and go back to the normal state. A timer would then go back to lights out mode if the user doesn't touch the screen for X seconds. The same code that worked with the ActionBar doesn't do the trick with a Toolbar
.
So, what I am using is:
setSystemUiVisibility()
using one of these combos:
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
minSdkVersion
is 16show()
and hide()
on itToolbar
and added a show()
and a hide()
method that do the same (first simply using setVisibility()
, and then using animations -- getting the same results)The LAYOUT_STABLE
made so that the appbar would end up behind the status bar, of course (as it implies a fitSystemWindows
. Since the appbar is a normal View in the view hierarchy and is not in the decor like the ActionBar was, it is affected by that flag. This was what I was seeing on screen:
Not immediately clear what the toolbar bounds are, as the app bar is dark on dark, but you can see the title is cut and "misaligned". This is because the toolbar was correctly sized but behind the status bar. My main problem was at that point that there is no public API to get the status bar height, rectangle or anything else to shift my app bar vertically to show below the status bar.
Testing was performed mostly on a N5 on LPX13D (latest Lollipop public build at the time of writing), but the same could be seen happening on Android 4.4.
That said, after quite some time and some failed attempts at making it work in a not-too-hacky way (including the rather desperate attempt of trying to put it into the decor myself), I resorted to this nasty way of making it work:
In onResume
:
a. Call setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE)
even when I wouldn't normally do it (landscape)
b. Register an OnPreDrawListener
In the OnPreDrawListener
:
a. Get the root view using View root = getRootView().findViewById(R.id.my_root)
b. Get the root view height: int rootTop = getAbsoluteViewTop(root)
(see below)
c. Use that top (intending it as a status bar height) as a paddingTop for the appbar
d. Set the SystemUiVisibility I'd normally use (LAYOUT_STABLE
etc)
e. Suppress the drawing pass
OnPreDrawListener
This is the getAbsoluteViewTop()
method:
private int getAbsoluteViewTop(View view) {
int[] location = new int[2];
view.getLocationOnScreen(location);
return location[LOCATION_Y];
}
tl;dr: there is no way to do a proper "lights out" mode with a Toolbar
unless hacky hacks are employed.
Question: is there an official and clean way to implement this lights out mode with Toolbar
?
I couldn't find anything in the docs. The status bar is not accessible (and all the ways to find out its size you can find on SO are broken, FYI). But maybe I'm missing something. I would love to get rid of this hack.
How do I fix AppCompat error v7? "You must have the latest versions of SDK Tools / Build Tools / Platform Tools." This trick resolved my problem. I have all updated Tools except "Build Tools". So I just update the "Build Tools", restarted eclipse then clean "appcompat" project and found my problem is solved.
453. An Android support library that enables the use of the ActionBar and Material Design specific implementations such as Toolbar for older devices down to Android v2.
I've found fitssystemwindows
pretty unreliable as well when you want some elements of the view hierarchy to be fullscreen and some elements to be below the status bar or action bar. But I've never seen the action bar behind the status bar. Is the Toolbar set as the activity actionbar? Are you using Window.FEATURE_ACTION_BAR_OVERLAY
? Anyway, if all you need is to get a number of pixels for the paddingTop
in onResume()
, it might be a bit cleaner (still hacky though) to do something like the following rather than use OnPreDrawListener
s.
class MyVideoActivity extends Activity {
Toolbar bar;
//...
@Override protected void onResume() {
super.onResume();
bar.setPaddingTop(getStatusBarHeight());
}
int getStatusBarHeight() {
int result = 0;
Resources res = getResources();
int resourceId = res.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = res.getDimensionPixelSize(resourceId);
}
return result;
}
}
Not sure if this will help but have you looked at using
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
in the onCreate method of your video activity? It might be a good starting point. This basically hides the status bar and makes my video full screen.
This is the layout I also use:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/black">
<VideoView
android:id="@id/videoSurface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:layout_centerInParent="true"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_gravity="center"
/>
</RelativeLayout>
I know some of the parameters are redundant but in the end it gives me the desired effect I wanted. It might be a good starting point for you?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With