I know that I can make the ActionBar overlay using requestFeature(Window.FEATURE_ACTION_BAR_OVERLAY)
and can toggle/show the status bar in my screen (by switching between FLAG_FULLSCREEN and FLAG_FORCE_NOT_FULLSCREEN).
This works great. However, I don't want my layout moving when I toggle the status bar.
I know that I can make the status bar "overlay" (albeit not transparently) the content using:
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
This works also great, except for the (expected) consequence that, when using an ActionBar, the ActionBar gets half cut off - half of it is under the status bar basically.
So I am wondering, is there a way to "move the ActionBar down" by the status bar's height in this case?
I know that in worse case, I can do this with a custom view that lives within the layout, but I rather not do this (want to benefit from the ActionBar).
thanks!
so apparently, you can do this in Jellybean. google includes two examples in the api docs. here is a link: http://developer.android.com/reference/android/view/View.html#setSystemUiVisibility%28int%29
summary:
use setSystemUiVisibility on a view to toggle visibility (on jellybean+).
It's not perfect, but this is how I have achieved what you want:
In onCreate:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Then:
private void hideStatusBar() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN);
}
private void showStatusBar() {
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
I also have a style on the activity with the following:
<style name="readingStyle" parent="#style/Theme.Sherlock">
<item name="android:windowActionBarOverlay">true</item>
<item name="windowActionBarOverlay">true</item>
</style>
Your activity will shift down when the status bar shows, but I don't think it's too noticeable.
Why you dont make it in the Manifest
android:theme="#android:style/Theme.Black.NoTitleBar"
than you have no statusbar and more space for the Actionbar??
Put this method in onCreate() method activity:
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
refer: link
Related
I have to make layout, where top of the layout should be drawn under SystemBars. (min API level for this app is 22)
I set these flags to achieve that. In other activities I can draw whole fragment with views under SystemBars, but here I cant do it.
I used this code to allow layout to be drawn under SystemBars
window.apply {
addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
statusBarColor = resources.getColor(android.R.color.transparent)
navigationBarColor = resources.getColor(android.R.color.transparent)
setBackgroundDrawable(background)
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
}
This is result in app:
I need to draw that grey area under system bar.
Update:
#Redman solution worked only partially.
Now I can draw under StatusBar but also I can draw under software buttons (navigationButtons) as you can see at screen below. Is there any way how to allow layout to be drawn under SystemBars but do not allow it under navigationButtons? Because that code what I've posted works for different fragments in app. But in other fragments I don't have ImageView as a part of ToolBar. If you have just ToolBar with for example 2-color gradient background and some backButton + SearchView, it is working fine. But as I add ImageView, ImageView will not "slide" under top SystemBar(aka StatusBar). Even in image above you can clearly see that green color (it's ToolBar background drawn under StatusBar). But ImageView is not allowed to be drawn under that bar.
The only way how to achieve that was with that special line of code
window.apply {
setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
}
but this line also allowed to draw layout content under NavigationButtons (which is an issue).
In your Activity Theme add these properties
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
and in parent layout add property
android:fitsSystemWindows="true"
Edit
Try this to do it programmatically, it should work above on devices having kitkat and above
window.apply {
setFlags( WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS)
}
use toolbar view in your xml file. See below example
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="#dimen/height_50dp"
android:background="#f1f1f1">
\\define your any element here. Like back arrow or title
</android.support.v7.widget.Toolbar>
All you need to do is set these properties in your theme:
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowTranslucentNavigation">true</item>
Your activity / container layout you wish to have a transparent status bar needs this property set:
android:fitsSystemWindows="true"
It is generally not possible to perform this for sure on pre-kitkat, looks like you can do it but some strange code makes it so.
EDIT: I would recommend this lib: https://github.com/jgilfelt/SystemBarTint for lots of pre-lollipop status bar color control.
Well after much deliberation I've learned that the answer to totally disabling the translucency or any color placed on the status bar and navigation bar for lollipop is to set this flag on the window:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Window w = getWindow(); // in Activity's onCreate() for instance
w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
}
How about this:
Window window = getWindow();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(ContextCompat.getColor(this, R.color.primary_dark));
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
int flags = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
window.addFlags(flags);
}
This should make Only StatusBar transparent.
If this didn't help, try adding:
<item name="android:windowTranslucentStatus">true</item>
To the Activity styles code in styles.xml.
I have a screen with a bottom toolbar aligned using the following styling
<style name="BottomToolbar" >
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">#color/WHITE</item>
<item name="android:layout_gravity">bottom</item>
<item name="android:layout_alignParentBottom">true</item>
<item name="android:minHeight">?attr/actionBarSize</item>
</style>
When I first enter my screen the toolbar is nicely aligned to the bottom of the screen.
However, If I go to full screen mode (which hides the toolbar) and then return to normal mode (which re-displays the toolbar) the toolbar is now placed slightly off the screen. It looks as if its shifted down the amount of the status bar that is hidden in full screen mode.
If I background my app and then foreground it, the bottom toolbar is rendered correctly.
I have a bar at the top of the screen (instead of an appBar) and that is rendered in the correct place. I can not work out why it is misplacing the bottom toolbar.
Its as if when it is determining the bottom of the parent it is not adjusting for the fact its not full screen height anymore.
What I have tried
I have tried setting "fitsSystemWindows="true"" on my toolbar when exiting full screen mode but that doesn't make a difference.
I have tried setting the toolbar to INVISIBLE rather than GONE when hiding it but that makes no difference.
EDIT 1 - Added Code snippet of how I go into and out of full screen
I go into full screen using the following
getActivity().getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
I exit full screen by using the following code
getActivity().getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
EDIT 2 - View is not shoved off the bottom, its height is too small
It appears that the bottom view is not shoved off the bottom of the screen, its height is shrunk and smaller than it should be.
The bottom view is a LinearLayout with its height set to "wrap_content" but it appears the height is not calculated correctly as its shorter than its contents and hence the bottom of its contents are cut off.
Edit 3 - devices the issues presents on
Further investigation showed the issue only presents on devices which do not have the on screen navigation bar. For example the issue is on my Samsung 10" Tablet but not on my Nexus 5x.
If I remove the following flag the issue appears to be fixed
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
The Google doc for this flag is "When using other layout flags, we would like a stable view of the content insets given to fitSystemWindows(Rect)."
https://developer.android.com/reference/android/view/View.html
The docs say
"You may also need to use SYSTEM_UI_FLAG_LAYOUT_STABLE to help your app maintain a stable layout." (https://developer.android.com/training/system-ui/status.html) and
"It's good practice to include other system UI flags (such as SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION and SYSTEM_UI_FLAG_LAYOUT_STABLE) to keep the content from resizing when the system bars hide and show." (https://developer.android.com/training/system-ui/immersive.html)
I'm getting same issue. I also searched on google but not getting solution.
I have apply 100 milliseconds delay on onBackPressed() because I have used setSystemUiVisibility but It is taking time.
Issue - Fragment is calling before setSystemUiVisibility because setSystemUiVisibility is taking time so we need to set delay on back press.
public static void hideToolbarFoProfile(Context mContext) {
Activity mActivity = (Activity) mContext;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window w = Objects.requireNonNull(mActivity).getWindow();
w.getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
((MainActivity) Objects.requireNonNull(mActivity)).toolbar.setVisibility(View.GONE);
}
public static void showToolbarFoProfile(Context mContext) {
Activity mActivity = (Activity) mContext;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window w = Objects.requireNonNull(mActivity).getWindow();
w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
w.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
}
}
((MainActivity) Objects.requireNonNull(mActivity)).toolbar.setVisibility(View.VISIBLE);
}
new Handler().postDelayed(() -> {
Objects.requireNonNull(getActivity()).onBackPressed();
}, 100);
My problem:
I exit from a fullscreen activity to a Dark Action theme activity.
I pressed back button on the soft keyboard to go back to fullscreen activity.
The views in the bottom were getting cut off suddenly.
I solved this by overriding onBackPressed() method and restarting my Activity:
#Override
public void onBackPressed() {
startActivity(new Intent(getApplicationContext(), YourActivityHere.class));
}
This should recreate the activity. It is a good hack if you can apply.
I am working with an activity that has a few different stages. It is designed like a wizard so a few sections of it are tutorial like pages where I hide the toolbar and status bar. The Activity starts off with the toolbar hidden. In each of the fragments, I have an onToolbarShown(ActionBar ab) (called in the base fragments onStart() method) which I use to edit the title, if the back button shows etc, and then I call the showToolbar method below:
public void showSystemUi(boolean show){
if(show){
KKDeviceUtil.showSystemUI(mRootLayout);
}else {
KKDeviceUtil.hideSystemUI(mRootLayout);
}
}
#Override
public void showToolbar(boolean show){
if(getSupportActionBar() != null){
showSystemUi(show);
if(show) {
mRootLayout.setFitsSystemWindows(true);
getSupportActionBar().show();
}else{
getSupportActionBar().hide();
mRootLayout.setFitsSystemWindows(false);
}
}
}
(showSystemUi is the stock show/hide method suggested by android here)
The problem is that the first time I show the toolbar, the status bar is the wrong colour and the layout is shunted down by the height of the status bar. As seen here:
When I next switch fragments, the problem clears up:
And if I go back to the previous fragment, it looks correct:
I don't get this problem if I never hide the toolbar/system windows in the first place. I originally had some of the operations in a different order and thought that re-arranging them could help, but It didn't seem to make any difference. I also tried calling setStatusBarColor but that had no effect. I also have <item name="android:statusBarColor">#color/status_bar_color</item> in my v21/styles.xml which is the correct colour for my status bar, and my primaryDark is the same colour as the screenshot (buggy) above shows.
I can't seem to find what I am doing wrong here, is this the correct way to show/hide my toolbar/system ui and why does this only happen on the first showing of the toolbar?
(Note: it is hard to see from the screenshots, but in the first screenshot, the 'Done' button is much closer to the bottom than the correct placing in the third screenshot)
Please see below i've shown you demo style that will reflect color on the status bar.
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/side_bar_color</item>
<item name="colorPrimaryDark">#color/side_bar_color</item>
<item name="colorAccent">#color/side_bar_color</item>
</style>
There "colorPrimaryDark" is that color which will used at status bar, you need to set this style to your application or activity at manifest class
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.
The issue
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:
An opaque Status Bar
setSystemUiVisibility() using one of these combos:
default: View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
lights out: 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 16
to show and hide the ActionBar I simply called show() and hide() on it
to implement the same behaviour on the app bar I subclassed Toolbar 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.
The hacky solution
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
In the next drawing pass, unregister the 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 and question
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.
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 OnPreDrawListeners.
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?
The problem is the following one : on one of my activities, I needed a custom layout for my action bar, and the only way to do it like needed was to have a transparent ActionBar over my screen. In order to do that, I marked the ActionBar as overlay, and specified the action bar background as transparent. This works when using Android >= 15, but in 14 and below, the ActionBar keeps its bottom border. I tried anything to remove it, with no avail.
Here is a picture to see it more clearly :
On API 14 :
On API 16:
The design is the following : the Action Bar is supposed to be transparent and in overlay mode, and behind it there is a background + the logo
<ImageView
android:id="#+id/action_bar_background"
android:layout_width="match_parent"
android:layout_height="#dimen/action_bar_accueil_total_height"
android:layout_alignParentTop="true"
android:contentDescription="#string/action_bar"
android:scaleType="fitXY"
android:src="#drawable/actionbar_logo_extended" />
<ImageView
android:id="#+id/home_gallica_logo"
android:layout_width="#dimen/largeur_logo_carrousel"
android:layout_height="#dimen/action_bar_accueil_total_height"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:contentDescription="#string/action_bar"
android:src="#drawable/logo_fullcolor" />
Some precisions : I use ABS, but this does not seem to be the source of the problem, as switching to the v7 support library did exactly the same thing.
Do anyone has an idea how to remove this bottom border ?
Following the advice and the test by Luksprog in the comment, I used Theme.Sherlock (instead of Theme.Sherlock.Light) in my action bar for this page, and copied from my old theme the settings I needed. This seems to have resolved the problem, but I'm not completely sure of the source. The only advice I can give to people who are going to see this will be to use Theme.Sherlock.
I've tried to make a simple activity to showcase the behavior but I didn't manage to do it. I used an Activity with the theme Theme.Sherlock:
android:theme="#style/Theme.Sherlock
and to make the overlay(in the onCreate() method):
requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); // Window from com.actionbarsherlock.view
//...
setContentView(content);
ActionBar ab = getSupportActionBar();
ab.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
You can hide the action bar at by calling hide() method:
ActionBar actionBar = getSupportActionBar();
actionBar.hide();
Or you can set this in your manifest if you want to hide it permanently:
<activity
android:theme="#android:style/Theme.NoTitleBar.Fullscreen"
>