Отображать показатели минус строка состояния?

Мне нужно получить размеры прямоугольника дисплея, который приложение может использовать на устройстве. Для этого я попытался использовать:

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

Моя проблема заключается в том, что она дает мне высоту всего экрана, а на дисплее есть панель "статус/уведомление" сверху, которую приложение не может использовать.

Мне нужно фактическое измерение, которое приложение может использовать.

Чтобы лучше понять вопрос, я оставлю изображение:

enter image description here

Ответ 1

Самый большой трюк для всего этого заключается в том, что вы обычно не можете получить доступ к истинному значению этого размера представления до завершения макета. Это означает, что onCreate() (и часто onResume() также) слишком рано в процессе выполнения вычислений. Следующий код предоставит вам представление, представляющее представление содержимого Activity, в котором вы можете проверить его высоту и ширину:

View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
Log.d("DISPLAY", content.getWidth() + " x " + content.getHeight());

Это также учитывает любые заголовки, которые вы могли установить в Activity. Вы также можете получить ссылку на корневой макет, который вы задали в качестве представления содержимого, когда XML завышен, и сделать то же самое, если этот макет установлен на fill_parent в обоих измерениях.

Хороший метод, когда я часто вызываю такие вызовы, - это onWindowFocusChanged(), который будет вызываться в момент, когда ваша активность будет только видимой для пользователя.

Надеюсь, что это поможет!

Ответ 2

Этот вызов не зависит от момента времени, когда вы его называете:

...
Point dimensions = getDisplayDimensions(context);
int width = dimensions.x;
int height = dimensions.y;
...

@NonNull
public static Point getDisplayDimensions( Context context )
{
    WindowManager wm = ( WindowManager ) context.getSystemService( Context.WINDOW_SERVICE );
    Display display = wm.getDefaultDisplay();

    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics( metrics );
    int screenWidth = metrics.widthPixels;
    int screenHeight = metrics.heightPixels;

    // find out if status bar has already been subtracted from screenHeight
    display.getRealMetrics( metrics );
    int physicalHeight = metrics.heightPixels;
    int statusBarHeight = getStatusBarHeight( context );
    int navigationBarHeight = getNavigationBarHeight( context );
    int heightDelta = physicalHeight - screenHeight;
    if ( heightDelta == 0 || heightDelta == navigationBarHeight )
    {
        screenHeight -= statusBarHeight;
    }

    return new Point( screenWidth, screenHeight );
}

public static int getStatusBarHeight( Context context )
{
    Resources resources = context.getResources();
    int resourceId = resources.getIdentifier( "status_bar_height", "dimen", "android" );
    return ( resourceId > 0 ) ? resources.getDimensionPixelSize( resourceId ) : 0;
}

public static int getNavigationBarHeight( Context context )
{
    Resources resources = context.getResources();
    int resourceId = resources.getIdentifier( "navigation_bar_height", "dimen", "android" );
    return ( resourceId > 0 ) ? resources.getDimensionPixelSize( resourceId ) : 0;
}

Хитрость заключается в том, что он сравнивает метрики экрана (то, что вы хотите по модулю строки состояния) и "реальные метрики", которые являются физическими пикселями устройства.

Высота строки состояния затем вычитается ad-hoc, если это еще не произошло.

(В моих тестах панель навигации, содержащая кнопки возврата и домой, уже была вычтена.)