How do I get the height of the screen in Android?

2019-06-20 17:12发布

问题:

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.

回答1:

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();
}


回答2:

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();
            } 
        });
    }
}


回答3:

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