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

Как я могу получить доступную высоту экрана в Android? Мне нужна высота минус строка состояния / строка меню или любые другие украшения, которые могут быть на экране, и мне нужно, чтобы это работало на всех устройствах. Кроме того, мне нужно знать это в функции onCreate. Я знаю, что этот вопрос задавался раньше, но я уже пробовал их решения, и ни одно из них не работает. Вот некоторые из вещей, которые я пробовал:

Это не учитывает строку состояния/строку меню:

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


person Dan Bray    schedule 14.06.2013    source источник
comment
Вы пробовали этот код: stackoverflow.com/a/13026919/611600   -  person Ali    schedule 14.06.2013
comment
Да, я пробовал это. Смотрите мой ответ ниже. Спасибо   -  person Dan Bray    schedule 27.06.2013
comment
возможный дубликат Получить высоту экрана в Android   -  person Karthik Balakrishnan    schedule 05.07.2013


Ответы (3)


Вы пытались выполнить расчеты высоты в onWindowFocusChanged класса Activity? Это устраняет проблемы с API, вычисляя то, что вы действительно хотите, не возясь с барами меню и т. д.

@Override
public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
        screenHeight=content.getHeight();
}
person smirciat    schedule 10.07.2013
comment
Я не пробовал это, но это будет работать, только если оно вызывается до OnCreate. - person Dan Bray; 10.07.2013
comment
Просто для моего собственного образования, какие методы или команды вы используете, которые необходимо выполнить до onCreate? В моем собственном решении я смог переместить многие функции из onCreate в onWindosFocusChange, и все стало правильно, как только экран отобразился для пользователя. - person smirciat; 10.07.2013
comment
Мне просто нужно получить правильную высоту и ширину экрана до или во время OnCreate, чтобы я мог задать своим объектам правильный размер и положение. У меня это работает. Смотрите мое решение. Кроме того, ваш код не будет работать, потому что сначала вызывается OnCreate. Все равно спасибо за помощь - person Dan Bray; 11.07.2013
comment
Я рад, что у вас есть то, что вам нужно! Спасибо, что проработали это вместе со мной! - person smirciat; 11.07.2013

Вот как мне удалось получить правильные размеры экрана для всех устройств:

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();
            } 
        });
    }
}
person Dan Bray    schedule 10.07.2013
comment
Вам действительно нужны эти виды сверху и снизу? Разве недостаточно иметь макет, охватывающий весь экран, и просто получить его высоту в onGlobalLayout? - person Giulio Piancastelli; 28.10.2013

Лучшее решение, которое мне удалось придумать, это:

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

Я тестировал его на API 7 - 17. К сожалению, на API 13 есть лишнее пространство внизу как по горизонтали, так и по вертикали, а на API 10, 8 и 7 недостаточно места внизу как по горизонтали, так и по вертикали. (Я не тестировал устаревшие API).

person Dan Bray    schedule 27.06.2013
comment
вы смогли найти решение этой проблемы? - person Jaydev; 27.07.2016