16

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?

Hrk
  • 2,725
  • 5
  • 29
  • 44
Kæmpe Klunker
  • 865
  • 1
  • 10
  • 27

5 Answers5

13

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.
Kæmpe Klunker
  • 865
  • 1
  • 10
  • 27
6

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

Community
  • 1
  • 1
rasmeta
  • 465
  • 2
  • 12
  • 1
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. – mmackh Apr 17 '15 at 10:51
  • Thank you for a constructive comment - you are right. I already edited the answer for future visitors. – rasmeta Apr 17 '15 at 10:56
2

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>
Maxime Claude
  • 965
  • 12
  • 27
0

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
}
Serega Maleev
  • 403
  • 5
  • 6
0

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.

Divyang M
  • 101
  • 1
  • 5