简体   繁体   English

在Android中获取屏幕高度

[英]Get the screen height in Android

How can I get the available height of the screen in Android? 如何在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. 另外,我需要在onCreate函数中知道这一点。 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: 以下是我尝试过的一些事情:

I have tested this code 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. 我已经在API 7-17上测试了这个代码。不幸的是,在API 13上,水平和垂直底部都有额外的空间,而在API 10,8和7上,水平和垂直底部没有足够的空间。 (I have not tested on obsolete APIs): (我没有测试过时的API):

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

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 correctly calculates the height of the status bar and menu bar in portrait but not in landscape. 在API 17上,它正确地以纵向方式计算状态栏和菜单栏的高度,但不以横向方式计算。 On API 10, it returns 0. I need it to work ideally on all devices or minimum API 7. 在API 10上,它返回0.我需要它在所有设备或最小API 7上理想地工作。

If you want the the display dimensions in pixels you can use getSize : 如果您想要显示尺寸(以像素为单位),可以使用getSize

Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;

If you're not in an Activity you can get the default Display via WINDOW_SERVICE : 如果您不在Activity ,则可以通过WINDOW_SERVICE获取默认显示:

WindowManager wm = (WindowManager) ctx.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
display.getSize(size);
int width = size.x;
int height = size.y;

Before getSize was introduced (in API level 13), you could use the getWidth and getHeight methods that are now deprecated: 在引入getSize之前(在API级别13中),您可以使用现已弃用getWidth和getHeight方法:

Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth();  // deprecated
int height = display.getHeight();  // deprecated

Referred from : Get screen dimensions in pixels 参考: 获取屏幕尺寸,以像素为单位

Working solution: 工作方案:

Create two dummy views : 创建两个虚拟视图:

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

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

Now, you should call getLocationOnScreen(int []) on these two views to receive their locations. 现在,您应该在这两个视图上调用getLocationOnScreen(int [])来接收它们的位置。 This function returns an array of 2 integers. 此函数返回2个整数的数组。 The first being x and the second y. 第一个是x,第二个是y。 We require only y. 我们只需要y。 Also note that correct values are returned only AFTER all the views are created and the onCreate method is exited. 另请注意,仅在创建所有视图并退出onCreate方法后才返回正确的值。

I tested this code on a regular fragment called from a viewpager. 我在一个从viewpager调用的常规片段上测试了这段代码。

The code was in the onCreateView method of my fragment. 代码在我的片段的onCreateView方法中。 I still had to use a postDelayed to get the correct values. 我仍然必须使用postDelayed来获取正确的值。

final View top = (View) view.findViewById(R.id.top);
    final View bottom = (View) view.findViewById(R.id.bottom);
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {

            int topLoc[] = new int[2];
            top.getLocationOnScreen(topLoc);
            int BottomLoc[] = new int[2];
            bottom.getLocationOnScreen(BottomLoc);
            Log.d(Constants.debug, "topY: "+ topLoc[1]+" BottomY:" + BottomLoc[1]);
        }
    },4000);

I have a Nexus 4. 我有一个Nexus 4。

In regular mode (status bar and the soft buttons shown) : 在常规模式下(状态栏和显示的软按钮):

07-05 02:28:23.367      565-565/com.torcellite.xx D/xx: topY: 50 BottomY:1182

In full screen mode (no status bar or soft buttons shown) : 在全屏模式下(未显示状态栏或软按钮):

07-05 02:29:17.360      707-707/com.torcellite.xx D/xx: topY: 0 BottomY:1280

All you have to do now is subtract. 你现在所要​​做的就是减去。

For Display 用于显示

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;

For Status Bar 对于状态栏

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

I haven't tried different API's but I'm using these values to figure out whether or not the onscreen keyboard is up. 我没有尝试过不同的API,但我正在使用这些值来判断屏幕键盘是否已启动。 Maybe you can try this and something comparable for width to get what you need? 也许你可以试试这个和宽度相当的东西来得到你需要的东西?

Rect r = new Rect();
view.getWindowVisibleDisplayFrame(r);
int
    screenHeight = view.getRootView().getHeight(), // height of the entire screen
    appHeight = r.bottom - r.top, // height of the entire app
    statusBarHeight = r.top, // height of the statusbar
    pageHeight = view.getHeight(), // height of the app without title
    appTitleHeight = appHeight - pageHeight, // height of the only the app title
    topHeight = statusBarHeight + appTitleHeight;
final View view = findViewById(R.id.root);
ViewTreeObserver vto = view.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        // calculate the height in here...

        ViewTreeObserver vto = view.getViewTreeObserver();
        vto.removeGlobalOnLayoutListener(this);
    }
});

Use this listener inside onCreate (available since api 1). onCreate使用此侦听器(自api 1起可用)。 You will need to assign the id @+id/root to the parent in your xml layout. 您需要将id @+id/root分配给xml布局中的父级。 There is no way the size can return a result of 0, since this listener makes a callback whenever the layouts has been positioned in view. 大小无法返回0的结果,因为只要布局已在视图中定位,此侦听器就会进行回调。

Display currentDisplay = getWindowManager().getDefaultDisplay();
        float dw = currentDisplay.getWidth();
        float dh = currentDisplay.getHeight();

dh will give you the screen height. dh会给你屏幕高度。

How about setting up a subclassed View as the root of the Activity. 如何将子类View设置为Activity的根目录。 Make this View fill the screen (it won't go past the status bar) and override onSizeChanged() . 使此视图填满屏幕(它不会超过状态栏)并覆盖onSizeChanged() Store those values and write a getter for them. 存储这些值并为它们编写一个getter。

It may not answer your question, but it could be useful to know (I was looking for it myself when I came to this question) that if you need a View's dimension but your code is being executed when its layout has not been laid out yet (for example in onCreate() ) you can setup a ViewTreeObserver.OnGlobalLayoutListener with View.getViewTreeObserver().addOnGlobalLayoutListener() and put the relevant code that needs the view's dimension there. 它可能无法回答你的问题,但知道(当我提出这个问题时我自己正在寻找它)可能是有用的,如果你需要一个View的维度,但你的代码在布局尚未布局时正在执行(例如在onCreate()中)您可以使用View.getViewTreeObserver()。addOnGlobalLayoutListener()设置ViewTreeObserver.OnGlobalLayoutListener,并在其中放置需要视图维度的相关代码。 The listener's callback will be called when the layout will have been laid out. 布局布局后将调用侦听器的回调。

courtesy-Francesco Feltrinelli 礼貌-Francesco Feltrinelli

You could try to do this. 你可以尝试这样做。

Get the height of the root layout that is loaded by the activity. 获取活动加载的根布局的高度。 In case it does not fill the screen put it inside another layout with a height property of fill_parent. 如果它没有填满屏幕,则将其放在另一个布局中,其高度属性为fill_parent。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM