Kæmpe Klunker
Kæmpe Klunker

Reputation: 865

Height of screen without status bar, actionBar and tabs

I have a ListView that I want each row to fill a third of the available screen. I have the status bar visible, and then an actionBar with slidingTabs beneath. I'm doing the current calculation like this:

height = context.getResources().getDisplayMetrics().heightPixels;
if (context.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
    {
        actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,context.getResources().getDisplayMetrics());
        Log.d("actionBarHeigth", actionBarHeight.toString());
    }

And setting the views height like this:

holder.imageView.getLayoutParams().height = (height - actionBarHeight*2) / 3;

But the rows of the list are slightly too big, and i guess it's the status bar causing it. How can I add the height of it to my calculations?

Upvotes: 16

Views: 17284

Answers (5)

Divyang M
Divyang M

Reputation: 111

I tried using

context.getResources().getIdentifier("status_bar_height", "dimen", "android")

but didn't work on some devices like Google Pixel 5 as its status bar has an unusual size and doesn't return true height.

After so many attempts, here is the solution that works with all the android versions. For that, you need to add a dummy view to your Activity.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:app="http://schemas.android.com/apk/res-auto"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent">

    <View
        android:id="@+id/view_main_top"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_alignParentTop="true" />

    <YOUR OTHER VIEWS HERE>

</RelativeLayout>

Then in code:

    OneShotPreDrawListener.add(binding.viewMainTop) {
        val pointsArray = IntArray(2)
        binding.viewMainTop.getLocationOnScreen(pointsArray)
        val statusBarHeight = pointsArray[1]
    }

pointsArray[1] Because we just want location Y, 0 is for X

Now you can use statusBarHeight anywhere in your project.

Upvotes: 0

Serega Maleev
Serega Maleev

Reputation: 403

Here some extensions that can helps you

fun Activity.heightScreen(): Int {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        windowManager.currentWindowMetrics.bounds.height()
    } else {
        val displayMetrics = DisplayMetrics()
        windowManager.defaultDisplay.getMetrics(displayMetrics)
        return displayMetrics.heightPixels
    }
}

/***
 * Gets the real ]Height of the display without subtracting any window decor or
 * applying any compatibility scale factors.
 * <p>
 * The size is adjusted based on the current rotation of the display.
 * @param view - your view
 */
fun Fragment.realHeightScreen(view: View = requireView()): Int {
    val point = Point()
    view.display.getRealSize(point)
    return point.y
}

/***
 *Gets the real Width of the display without subtracting any window decor or
 * applying any compatibility scale factors.
 * <p>
 * The size is adjusted based on the current rotation of the display.
 * @param view - your view
 */
fun Fragment.realWidthScreen(view: View = requireView()): Int {
    val point = Point()
    view.display.getRealSize(point)
    return point.x
}


fun getSoftNavigationBarSize(resources: Resources = Resources.getSystem()): Int {
    var result = 0
    val resourceId: Int = resources.getIdentifier("navigation_bar_height", "dimen", "android")
    if (resourceId > 0) {
        result = resources.getDimensionPixelSize(resourceId)
    }
    return result
}

Upvotes: 0

Maxime Claude
Maxime Claude

Reputation: 995

The easiest way is this:

int height = findViewById(R.id.rootView).getHeight();

rootView is the master root layout :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/rootView"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
      ...
</LinearLayout>

Upvotes: 2

rasmeta
rasmeta

Reputation: 475

You can use this code:

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

as described here: https://stackoverflow.com/a/3410200/1763138

Please try using this solution and tell us if it worked. ;)

Upvotes: 6

K&#230;mpe Klunker
K&#230;mpe Klunker

Reputation: 865

Based on @rasmeta 's answer I made this code and it does the trick. My rows are now exactly a third of the available screen. Here is how to get the height of the status bar:

int resource = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
    if (resource > 0) {
        statusBarHeight = context.getResources().getDimensionPixelSize(resource);
    }

And the calculation of the height of each row goes like this:

holder.imageView.getLayoutParams().height = (screenHeight - statusBarHeight - actionBarHeight*2) / 3;
// actionBarHeight * 2 because the tabs have the same height as the actionBar.

Upvotes: 13

Related Questions