Reputation: 865
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
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
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
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
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
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