Height of statusbar?

Android

Android Problem Overview


Is there a way to get the height of the statusbar + titlebar? Checking the dev forum shows the same question but no solution (that I could find).

I know we can get it after the initial layout pass, but I'm looking to get it in onCreate() of my activity.

Thanks

Android Solutions


Solution 1 - Android

Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int StatusBarHeight= rectgle.top;
int contentViewTop= 
    window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int TitleBarHeight= contentViewTop - StatusBarHeight;

   Log.i("*** Jorgesys :: ", "StatusBar Height= " + StatusBarHeight + " , TitleBar Height = " + TitleBarHeight); 

Get the Height of the status bar on the onCreate() method of your Activity, use this method:

public int getStatusBarHeight() { 
      int result = 0;
      int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
      if (resourceId > 0) {
          result = getResources().getDimensionPixelSize(resourceId);
      } 
      return result;
} 

Solution 2 - Android

For those, like me, who want to use it in your XML layouts:

<...
  android:layout_marginTop="@*android:dimen/status_bar_height"
  ... />

Don't be confused by that Android Studio (2.2 Preview 3 -- at the moment of writing) doesn't support this notion. The runtime does. I took it from the Google's source code.

Solution 3 - Android

Although this is an old question, I found that the answer didn't work in onCreate():

I found this code from here which does work in the onCreate() method

public int getStatusBarHeight() {
   int result = 0;
   int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
   if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
   }
   return result;
}

I hope this helps to anyone that runs into this issue.

Solution 4 - Android

The supported way of getting status bar height is to use WindowInsets class starting from API 21+:

customView.setOnApplyWindowInsetsListener((view, insets) -> {
    // Handle insets
    return insets.consumeSystemWindowInsets();
});

or WindowInsetsCompat for support libraries:

ViewCompat.setOnApplyWindowInsetsListener(customView, (view, insets) -> {
    // Handle insets
    return insets.consumeSystemWindowInsets();
});

You can also override the onApplyWindowInsets method inside the view:

public class CustomView extends View {
    @Override
    public WindowInsets onApplyWindowInsets(final WindowInsets insets) {
        final int statusBarHeight = insets.getStableInsetTop();
        return insets.consumeStableInsets();
    }
}

For further details, I'd recommend checking Chris Banes talk - Becoming a master window fitter (slides available here).

Solution 5 - Android

You could also take the dimension of the status bar found in the dimens.xml file of android using the way that this blog post describes.

This can get the height of the statusbar without the need to wait for drawing.

Quoting the code from the blog post:

public int getStatusBarHeight() {
  int result = 0;
  int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
  if (resourceId > 0) {
      result = getResources().getDimensionPixelSize(resourceId);
  }
  return result;
}

You need to put this method in a ContextWrapper class.

Solution 6 - Android

I would suggest next code:

Rect rect = new Rect();
Window window = activity.getWindow();
if (window != null) {
  window.getDecorView().getWindowVisibleDisplayFrame(rect);
  android.view.View v = window.findViewById(Window.ID_ANDROID_CONTENT);

  android.view.Display display = ((android.view.WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

  //return result title bar height
  return display.getHeight() - v.getBottom() + rect.top;   
}

Two examples:

  1. Device 1 brand: samsung, device: maguro, board: tuna, cpu_abi: armeabi-v7a, display: ICL53F.M420KREL08, manufacturer: samsung, model: Galaxy Nexus, ver.release: 4.0.2, ver.sdk: 14;

Screen resolution: 1280 x 720.There are no hardware buttons on this device.

Results:

rect: left=0 right=720 top=72 bottom=1208;
v: left=0 right=720 top=72 bottom=1208;
display: height=1208 width=720;
correct result=72;

Device 1 has title bar at the top of the screen and status bar with software buttons at the bottom of the screen.

  1. Device 2 device: bravo, board: bravo, cpu_abi: armeabi-v7a, display: FRG83G, manufacturer: HTC, model: HTC Desire, ver.release: 2.2.2, ver.sdk: 8,

Screen resolution: 800 x 400. This device has hardware buttons.

Results:

rect: left=0 right=480 top=38 bottom=800;
v: left=0 right=480 top=0 bottom=800;
display: height=800 width=480;
correct result: phone_bar_height=38;

Device 2 has title bar at the top of the screen and hasn't status bar at all.

Two solutions were suggested above:

A) v.getTop() - rect.top 

(it is incorrect for device 1 - it gives 0 instead of 72)

B) display.getHeight() - v.getHeight() 

(it is incorrect for device 2 - it gives 0 instead of 38)

Variant:

 display.getHeight() - v.getBottom() + rect.top

gives correct results in both cases.

Update

  1. One more example (third device): brand: LGE, device: v909, cpu_abi: armeabi-v7a, display: HMJ37, model: LG-V909, ver.release: 3.1, ver.sdk: 12

    rect: left=0 right=1280 top=0 bottom=720 v: left=0 right=1280 top=0 bottom=720 Display: height=768 width=1280 phone_bar_height=48

Device 3 has horizontal orientation, hasn't title bar at the top of the screen and has status bar at the bottom of the screen.

So, here:

int size_of_title_bar = rect.top;
int size_of_status_bar = display.getHeight() - v.getBottom();

It's correct for devices 2 and 3. I am not sure about device 1. User sent me screenshot of device 1. There is a status bar with software button there. But expression "display.getHeight() - v.getBottom()" gives 0.

Solution 7 - Android

Attach a runnable to one of your views in your onCreate method, and place the above code in there. This will cause the application to calculate the status bar + titlescreen height when they are attached to the screen.

Take a look at the code below:

myView.post(new Runnable() {

		@Override
		public void run() {
			Rect rectgle= new Rect();
            Window window= getWindow();
            window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
            int StatusBarHeight= rectgle.top;
            int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
            int TitleBarHeight= contentViewTop - StatusBarHeight;
	
		}
		
	});

If this still doesn't do the trick, try invoking the view's postDelayed method instead of post and adding a millisecond value as the second argument.

Solution 8 - Android

As of API 23 there is a better solution to getting the status bar height. API 23 adds a WindowInsets feature, so you can use this code to get the size of the system insets, in this case at the top.

public int getStatusBarHeight() {
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        return binding.mainContent.getRootWindowInsets().getStableInsetTop();
    }
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if(resourceId != 0) {
        return getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

Note that getRootWindowInsets() will return null until after the View has been attached to a Window so it can't be used directly in onCreate() but you can add a listener for the window attach and do it there - here I am adding the status bar inset to the size of my toolbar, which I hide and show, along with the status bar. When it's shown, I want the status bar over the top of it so I add the status bar height to the toolbar's top padding.

    binding.mainContent.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View view) {
            binding.toolbar.setPadding(binding.toolbar.getPaddingLeft(),
                binding.toolbar.getPaddingTop() + getStatusBarHeight(),
                binding.toolbar.getPaddingRight(), binding.toolbar.getPaddingBottom());
            binding.mainContent.removeOnAttachStateChangeListener(this);
        }

        @Override
        public void onViewDetachedFromWindow(View view) {

        }
    });

Solution 9 - Android

This may seem unrelated but most of the time, the reason that people look for the status bar height is to offset their own views so they are not placed under it.

By setting fitsSystemWindows on the view you want to "push down" to give space to the status bar, it will be done automatically and according to the size of the status bar on each device. Padding will be added to the view that has this property set to true.

Keep in mind that padding will only be added to the first view in the hierarchy with fitSystemWindows set to true

This applies to cases where the status bar is translucent for example. Make sure that you set a Theme to the activity that doesn't have fitSystemWindows set, otherwise the padding will be added to the activity instead (because it's first in the hierarchy).

This article is a good read on the subject

Solution 10 - Android

I think better way to calculate that is to get height of fullscreen minus our main layout

phoneBarsHeight = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight() 
	- mainView.getHeight();

And you can put it in onGlobalLayout(). This works on tablets too, I tried it on Theme.NoTitleBar, but it must always works.

Maybe you can even enhance it and use it onCreate() by changing mainView.getHeight() to mainView.getMeasuredHeight().

Solution 11 - Android

The solution posted by Jorgesys is very good, but it doesn't work inside onCreate() method. I guess it's because statusbar and titlebar are created after onCreate().

The solution is easy - you should put code inside runnable and execute it after onCreate() by using root.post((Runnable action) );

So the whole solution:

root = (ViewGroup)findViewById(R.id.root);
root.post(new Runnable() { 
    	public void run(){
    		Rect rectgle= new Rect();
            Window window= getWindow();
            window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
            int StatusBarHeight= rectgle.top;
            int contentViewTop= 
                 window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
            int TitleBarHeight= contentViewTop - StatusBarHeight;

            Log.i("***  jakkubu :: ", "StatusBar Height= " + StatusBarHeight +
    		   " , TitleBar Height = " + TitleBarHeight);
    	}
});

I find it here

Solution 12 - Android

Ok. Final answer!!! One that does not have side-effects, relies on documented behavior, supports Q, cutouts, devices with different status-bar size depending on orientation, &c.

protected void onCreate(Bundle savedInstanceState) {
     ...
     setContentView(R.layout.activity_main);
     ....
     // Use The topmost view of the activity, which 
    // is guaranteed to be asked about window insets/
     View rootView = findViewById(R.id.root_view_of_your_activity);
     ViewCompat.setOnApplyWindowInsetsListener(rootView, new OnApplyWindowInsetsListener() {
		@Override
	    public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) 
    {
        //THIS is the value you want.
		statusBarHeight = insets.getSystemWindowInsetTop();

        // Let the view handle insets as it likes.
		return ViewCompat.onApplyWindowInsets(v,insets);
	}
});

The callback occurs after onStart(), before first layout, and occasionally thereafter.

Solution 13 - Android

Targeting API 30, I've used successfully updated Nicklas answer (ref:https://stackoverflow.com/a/47125610/2163045)

In my example I'm adjusting dynamically custom toolbar height in fullscreen WindowCompat.setDecorFitsSystemWindows(window, false) Activity

Tested on GooglePixel 5

class MyActivity : ViewBindingActivity<LayoutBinding>() {
...

    override fun created(binding: LayoutBinding, savedInstanceState: Bundle?) {

        binding.root.setOnApplyWindowInsetsListener { _, insets ->
            val statusBarHeight = insets.getInsets(WindowInsets.Type.statusBars()).top // <- HERE YOU ARE
            val toolbarHeight = getDimenPx(R.dimen.toolbar_height)
            binding.toolbar.layoutParams.height = statusBarHeight + toolbarHeight
            insets
        }
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser291701View Question on Stackoverflow
Solution 1 - AndroidJorgesysView Answer on Stackoverflow
Solution 2 - AndroidAleksey GureievView Answer on Stackoverflow
Solution 3 - AndroidraukodraugView Answer on Stackoverflow
Solution 4 - AndroidyarqView Answer on Stackoverflow
Solution 5 - AndroidLKallipoView Answer on Stackoverflow
Solution 6 - AndroiddvpublicView Answer on Stackoverflow
Solution 7 - AndroidKachiView Answer on Stackoverflow
Solution 8 - AndroidClydeView Answer on Stackoverflow
Solution 9 - AndroidlbarbosaView Answer on Stackoverflow
Solution 10 - AndroidMikooosView Answer on Stackoverflow
Solution 11 - AndroidjakkubuView Answer on Stackoverflow
Solution 12 - AndroidRobin DaviesView Answer on Stackoverflow
Solution 13 - AndroidmurtView Answer on Stackoverflow