18

如何在 Android 中获取屏幕的可用高度?我需要高度减去状态栏/菜单栏或屏幕上可能出现的任何其他装饰,并且我需要它适用于所有设备。另外,我需要在 onCreate 函数中知道这一点。我知道以前有人问过这个问题,但我已经尝试过他们的解决方案,但都没有奏效。以下是我尝试过的一些事情:

我已经在 API 7 - 17 上测试了这段代码。不幸的是,在 API 13 上,底部水平和垂直都有额外的空间,而在 API 10、8 和 7 上,底部水平和垂直都没有足够的空间。(我没有在过时的 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);

这不考虑状态栏/菜单栏:

Display display = getWindowManager().getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();

这也不是:

Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
screenWidth = size.x;
screenHeight = size.y;

也不是这个:

Point size = new Point();
getWindowManager().getDefaultDisplay().getRealSize(size);
screenWidth = size.x;
screenHeight = size.y;

这不起作用:

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
}

然后我使用以下代码从屏幕高度中减去状态栏和菜单栏的高度:

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;

在 API 17 上,它可以正确计算纵向状态栏和菜单栏的高度,而不是横向计算。在 API 10 上,它返回 0。我需要它在所有设备或最低 API 7 上理想地工作。

4

9 回答 9

7

如果您想要以像素为单位的显示尺寸,您可以使用getSize

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

如果您不在,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;

getSize引入之前(在 API 级别 13 中),您可以使用现在已弃用的 getWidth 和 getHeight 方法:

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

参考自: 获取屏幕尺寸(以像素为单位)

于 2013-07-06T05:45:30.010 回答
5

工作解决方案:

创建两个虚拟视图:

 <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" />

现在,您应该调用getLocationOnScreen(int [])这两个视图来接收它们的位置。该函数返回一个由 2 个整数组成的数组。第一个是 x,第二个是 y。我们只需要 y。另请注意,仅在创建所有视图并onCreate退出该方法后才返回正确的值。

我在从 viewpager 调用的常规片段上测试了此代码。

代码在onCreateView我的片段的方法中。我仍然必须使用 apostDelayed来获得正确的值。

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

我有一个 Nexus 4。

在常规模式下(显示状态栏和软按钮):

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

在全屏模式下(不显示状态栏或软按钮):

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

你现在要做的就是减法。

于 2013-07-04T21:04:01.477 回答
2
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);
    }
});

在里面使用这个监听onCreate器(从 api 1 开始可用)。您需要将 id 分配给@+id/rootxml 布局中的父级。大小不可能返回 0 的结果,因为只要布局在视图中定位,此侦听器就会进行回调。

于 2013-07-04T09:06:42.220 回答
2

用于展示

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

对于状态栏

public int getStatusBarHeight() {
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }
于 2013-06-27T21:56:09.727 回答
2

我没有尝试过不同的 API,但我正在使用这些值来确定屏幕键盘是否启动。也许你可以试试这个和类似的宽度来获得你需要的东西?

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;
于 2013-07-01T16:40:34.530 回答
1
Display currentDisplay = getWindowManager().getDefaultDisplay();
        float dw = currentDisplay.getWidth();
        float dh = currentDisplay.getHeight();

dh会给你屏幕高度。

于 2013-06-28T05:52:41.293 回答
0

它可能无法回答您的问题,但如果您需要 View 的尺寸但您的代码在其布局尚未布局时正在执行,那么了解(当我遇到这个问题时我自己正在寻找它)可能会很有用(例如在 onCreate() 中)您可以使用 View.getViewTreeObserver().addOnGlobalLayoutListener() 设置 ViewTreeObserver.OnGlobalLayoutListener 并将需要视图尺寸的相关代码放在那里。布局布局后,将调用侦听器的回调。

礼貌-Francesco Feltrinelli

你可以尝试这样做。

于 2013-07-03T13:15:56.897 回答
0

如何将子类视图设置为 Activity 的根。让这个 View 填满屏幕(它不会越过状态栏)并覆盖onSizeChanged()。存储这些值并为它们编写一个 getter。

于 2013-07-02T19:06:33.697 回答
0

获取活动加载的根布局的高度。如果它没有填满屏幕,请将其放在另一个布局中,其高度属性为 fill_parent。

于 2013-07-04T11:55:37.147 回答