How can I get the available height of the screen in Android? I need to the height minus the status bar / menu bar or any other decorations that might be on screen and I need it to work for all devices. Also, I need to know this in the onCreate function. I know this question has been asked before but I have already tried their solutions and none of them work. Here are some of the things I have tried:
This does not take into account the status bar / menu bar:
Display display = getWindowManager().getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();
Neither does this:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
screenWidth = size.x;
screenHeight = size.y;
Nor this:
Point size = new Point();
getWindowManager().getDefaultDisplay().getRealSize(size);
screenWidth = size.x;
screenHeight = size.y;
This does not work:
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
// since SDK_INT = 1;
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
try
{
// used when 17 > SDK_INT >= 14; includes window decorations (statusbar bar/menu bar)
screenWidth = (Integer) Display.class.getMethod("getRawWidth").invoke(display);
screenHeight = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
}
catch (Exception ignored)
{
// Do nothing
}
try
{
// used when SDK_INT >= 17; includes window decorations (statusbar bar/menu bar)
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(display, realSize);
screenWidth = realSize.x;
screenHeight = realSize.y;
}
catch (Exception ignored)
{
// Do nothing
}
I then used the following code to subtract the height of the status bar and menu bar from the screen height:
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
result = getResources().getDimensionPixelSize(resourceId);
screenHeight -= result;
result = 0;
if (screenHeight >= screenWidth)
resourceId = getResources().getIdentifier("navigation_bar_height", "dimen", "android");
else
resourceId = getResources().getIdentifier("navigation_bar_height_landscape", "dimen", "android");
if (resourceId > 0)
result = getResources().getDimensionPixelSize(resourceId);
screenHeight -= result;
On API 17 it gives it correctly calculates the height of the status bar and menu bar in portrait but not in landscape. On API 10, it returns 0. I need it to work ideally on all devices or minimum API 10.
Have you tried doing your height calculations in onWindowFocusChanged of the Activity class? This eliminates API troubles by calculating what you really want, not messing with menu bars etc.
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
screenHeight=content.getHeight();
}
Here is how I managed to get the correct screen dimensions for all devices:
public class MainActivity extends Activity
{
static int ScreenWidth;
static int ScreenHeight;
static int ScreenWidthLandscape;
static int ScreenHeightLandscape;
private RelativeLayout layout;
private RelativeLayout.LayoutParams params;
private View top;
private View bottom;
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
layout = new RelativeLayout(this);
top = new View(this);
bottom = new View(this);
RelativeLayout.LayoutParams viewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
viewParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
top.setLayoutParams(viewParams);
viewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
viewParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
bottom.setLayoutParams(viewParams);
layout.addView(top);
layout.addView(bottom);
setContentView(layout);
final Intent intent = new Intent(this, myPackage.learnSpanishVerbs.Start.class);
final View view = getWindow().getDecorView().getRootView();
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
@Override
public void onGlobalLayout()
{
int topLoc[] = new int[2];
top.getLocationOnScreen(topLoc);
int BottomLoc[] = new int[2];
bottom.getLocationOnScreen(BottomLoc);
boolean portrait = getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE;
if (portrait)
{
ScreenWidth = top.getWidth();
ScreenHeight = BottomLoc[1] - topLoc[1];
}
else
{
ScreenWidthLandscape = top.getWidth();
ScreenHeightLandscape = BottomLoc[1] - topLoc[1];
}
if (Build.VERSION.SDK_INT < 16)
view.getViewTreeObserver().removeGlobalOnLayoutListener(this);
else
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
startActivity(intent);
finish();
}
});
}
}
The best solution I have managed to come up with is this:
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
screenWidth = metrics.widthPixels;
screenHeight = metrics.heightPixels;
TypedValue tv = new TypedValue();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
screenHeight -= TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
screenHeight -= getResources().getDimensionPixelSize(resourceId);
I have tested it on API 7 - 17. Unfortunately, on API 13 there is extra space at bottom both horizontally and vertically and on API 10, 8, and 7 there is not enough space at the bottom both horizontally and vertically. (I have not tested on obsolete APIs).