Получить высоту экрана в Android

Как получить доступную высоту экрана в 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. Любая помощь была бы с благодарностью.

Ответ 1

Рабочее решение:

Создайте два фиктивных представления:

 <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 моего фрагмента. Мне все равно пришлось использовать 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);

У меня есть 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

Все, что вам нужно сделать, это вычесть.

Надеюсь, что это поможет. Приветствия.

Ответ 2

Если вам нужны размеры экрана в пикселях, вы можете использовать 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

Реферат: Получить размеры экрана в пикселях

Ответ 3

Для отображения

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

Ответ 4

Я не пробовал использовать другой 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;

Ответ 5

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/root родительскому элементу в xml-макете. Невозможно, чтобы размер возвращал результат 0, так как этот прослушиватель выполняет обратный вызов всякий раз, когда макеты расположены в поле зрения.

Ответ 6

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

dh даст вам высоту экрана.

Ответ 7

Как создать подклассу View как корень Activity. Сделайте этот вид заполняющим экран (он не пройдет мимо строки состояния) и переопределит onSizeChanged(). Сохраните эти значения и напишите для них геттер.

Ответ 8

Он может не отвечать на ваш вопрос, но может быть полезно знать (я был ища его сам, когда я пришел к этому вопросу), что если вам понадобится Просмотрите размер, но ваш код выполняется, когда его макет еще не выложены (например, в onCreate()) вы можете настроить ViewTreeObserver.OnGlobalLayoutListener с View.getViewTreeObserver(). AddOnGlobalLayoutListener() и поставьте соответствующий код, для которого требуется измерение вида. Слушатель обратный вызов будет вызываться, когда макет будет выложен.

любезность - Франческо Фелтринелли

Вы можете попробовать сделать это.

Ответ 9

Получить высоту корневого макета, загружаемого активностью. Если он не заполняет экран, поместите его в другой макет с свойством height fill_parent.