Height of statusbar?

Viewed 95358

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

14 Answers

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).

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

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.

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
        }
    }
}

Current actual way:

ViewCompat.setOnApplyWindowInsetsListener(toolbar) { view, windowInsets ->
     val insets = windowInsets.getInsets(WindowInsetsCompat.Type.statusBars())
     view.updateLayoutParams<MarginLayoutParams> {
         topMargin = insets.top
     }
     WindowInsetsCompat.CONSUMED
}

Google recommends using it like this if you want to support edge-to-edge in your app.

Related