Высота статусной панели?

Есть ли способ получить высоту строки состояния + заголовок? Проверка форума dev показывает тот же вопрос, но не решение (которое я мог найти).

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

Спасибо

Ответ 1

Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int StatusBarHeight= rectgle.top;
int contentViewTop= 
    window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int TitleBarHeight= contentViewTop - StatusBarHeight;

   Log.i("*** Jorgesys :: ", "StatusBar Height= " + StatusBarHeight + " , TitleBar Height = " + TitleBarHeight); 

Получите высоту строки состояния в onCreate() методе вашей деятельности, используйте этот метод:

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

Ответ 2

Хотя это старый вопрос, я обнаружил, что ответ не работает в onCreate():

Я нашел этот код здесь, который работает в методе onCreate()

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

Я надеюсь, что это поможет любому, кто сталкивается с этой проблемой.

Ответ 3

Для тех, кто любит использовать его в ваших XML-макетах,

<...
  android:layout_marginTop="@*android:dimen/status_bar_height"
  ... />

Не смущайтесь тем, что Android Studio (2.2 Preview 3 - на момент написания) не поддерживает это понятие. Среда выполнения. Я взял его из исходного кода Google.

Ответ 4

Поддерживаемый способ получения высоты строки состояния - использовать класс WindowInsets, начиная с API 21+:

customView.setOnApplyWindowInsetsListener((view, insets) -> {
    // Handle insets
    return insets.consumeSystemWindowInsets();
});

или WindowInsetsCompat для библиотек поддержки:

ViewCompat.setOnApplyWindowInsetsListener(customView, (view, insets) -> {
    // Handle insets
    return insets.consumeSystemWindowInsets();
});

Вы также можете переопределить метод onApplyWindowInsets внутри представления:

public class CustomView extends View {
    @Override
    public WindowInsets onApplyWindowInsets(final WindowInsets insets) {
        final int statusBarHeight = insets.getStableInsetTop();
        return insets.consumeStableInsets();
    }
}

Для получения более подробной информации, я бы порекомендовал проверить выступление Криса Бэйнса - стать мастером по сборке окон (слайды доступны здесь).

Ответ 5

Я бы предложил следующий код:

Rect rect = new Rect();
Window window = activity.getWindow();
if (window != null) {
  window.getDecorView().getWindowVisibleDisplayFrame(rect);
  android.view.View v = window.findViewById(Window.ID_ANDROID_CONTENT);

  android.view.Display display = ((android.view.WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();

  //return result title bar height
  return display.getHeight() - v.getBottom() + rect.top;   
}

Два примера:

1) Устройство 1 бренд: samsung, устройство: maguro, доска: тунец, cpu_abi: armeabi-v7a, дисплей: ICL53F.M420KREL08, производитель: samsung, модель: Galaxy Nexus, ver.release: 4.0.2, ver.sdk: 14;

Разрешение экрана: 1280 x 720. На этом устройстве нет аппаратных кнопок.

Результаты:

rect: left=0 right=720 top=72 bottom=1208;
v: left=0 right=720 top=72 bottom=1208;
display: height=1208 width=720;
correct result=72;

Устройство 1 имеет строку заголовка в верхней части экрана и строку состояния с программными кнопками в нижней части экрана.

2) Устройство 2 устройство: браво, доска: браво, cpu_abi: armeabi-v7a, дисплей: FRG83G, производитель: HTC, модель: HTC Desire, ver.release: 2.2.2, ver.sdk: 8,

Разрешение экрана: 800 x 400. Это устройство имеет аппаратные кнопки.

Результаты:

rect: left=0 right=480 top=38 bottom=800;
v: left=0 right=480 top=0 bottom=800;
display: height=800 width=480;
correct result: phone_bar_height=38;

Устройство 2 имеет строку заголовка в верхней части экрана и вообще не имеет строки состояния.

Были предложены два решения:

A) v.getTop() - rect.top 

( неверно для устройства 1 - он дает 0 вместо 72)

B) display.getHeight() - v.getHeight() 

( неверно для устройства 2 - он дает 0 вместо 38)

Вариант:

 display.getHeight() - v.getBottom() + rect.top

дает правильные результаты в обоих случаях.

Обновление

3) Еще один пример (третье устройство):  бренд: LGE,  устройство: v909,  cpu_abi: armeabi-v7a,  дисплей: HMJ37,  модель: LG-V909,  ver.release: 3.1,  ver.sdk: 12

rect: left=0 right=1280 top=0 bottom=720
v: left=0 right=1280 top=0 bottom=720
Display: height=768 width=1280
phone_bar_height=48

Устройство 3 имеет горизонтальную ориентацию, не имеет заголовка в верхней части экрана и имеет строку состояния в нижней части экрана.

Итак, здесь:

int size_of_title_bar = rect.top;
int size_of_status_bar = display.getHeight() - v.getBottom();

Это правильно для устройств 2 и 3. Я не уверен в устройстве 1. Пользователь отправил мне снимок экрана с устройства 1. Там есть строка состояния с программной кнопкой. Но выражение "display.getHeight() - v.getBottom()" дает 0.

Ответ 6

Вы также можете измерить размер строки состояния, найденный в файле измерения .xml на Android, используя способ, описанный в этом блоге.

Это может получить высоту строки состояния без необходимости ждать рисования.

Цитирую код из поста в блоге:

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

Вам нужно поместить этот метод в класс ContextWrapper.

Ответ 7

Прикрепите runnable к одному из ваших представлений в вашем методе onCreate и поместите туда вышеприведенный код. Это заставит приложение вычислить строку состояния + высоту экрана заголовка, когда они будут прикреплены к экрану.

Взгляните на код ниже:

myView.post(new Runnable() {

        @Override
        public void run() {
            Rect rectgle= new Rect();
            Window window= getWindow();
            window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
            int StatusBarHeight= rectgle.top;
            int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
            int TitleBarHeight= contentViewTop - StatusBarHeight;

        }

    });

Если это все еще не делает трюк, попробуйте вызвать метод postDelayed view вместо сообщения и добавить значение миллисекунды в качестве второго аргумента.

Ответ 8

Я думаю, что лучший способ рассчитать, чтобы получить высоту полноэкранного экрана минус наш основной макет

phoneBarsHeight = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight() 
    - mainView.getHeight();

И вы можете поместить его в onGlobalLayout(). Это также работает на планшетах, я пробовал его на Theme.NoTitleBar, но он всегда должен работать.

Возможно, вы можете даже улучшить его и использовать его onCreate(), изменив mainView.getHeight() на mainView.getMeasuredHeight().

Ответ 9

Решение, отправленное Jorgesys, очень хорошо, но оно не работает внутри метода onCreate(). Я думаю, это потому, что statusbar и titlebar создаются после onCreate().

Решение легко - вы должны поместить код внутри runnable и выполнить его после onCreate() с помощью root.post((Runnable action) );

Итак, все решение:

root = (ViewGroup)findViewById(R.id.root);
root.post(new Runnable() { 
        public void run(){
            Rect rectgle= new Rect();
            Window window= getWindow();
            window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
            int StatusBarHeight= rectgle.top;
            int contentViewTop= 
                 window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
            int TitleBarHeight= contentViewTop - StatusBarHeight;

            Log.i("***  jakkubu :: ", "StatusBar Height= " + StatusBarHeight +
               " , TitleBar Height = " + TitleBarHeight);
        }
});

Я нахожу его здесь

Ответ 10

Как и в случае API 23, существует лучшее решение для получения высоты строки состояния. API 23 добавляет функцию WindowInsets, поэтому вы можете использовать этот код, чтобы получить размер системных вложений, в этом случае вверху.

public int getStatusBarHeight() {
    if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
        return binding.mainContent.getRootWindowInsets().getStableInsetTop();
    }
    int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
    if(resourceId != 0) {
        return getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

Обратите внимание, что getRootWindowInsets() будет возвращать значение null до тех пор, пока представление не будет прикреплено к окну, поэтому его нельзя использовать непосредственно в onCreate(), но вы можете добавить слушателя для прикрепления окна и сделать его там - здесь я Я добавляю вставку строки состояния к размеру моей панели инструментов, которую я скрываю и показываю вместе со строкой состояния. Когда он будет показан, я хочу, чтобы строка состояния была сверху, поэтому я добавляю высоту строки состояния в верхнюю панель панели инструментов.

    binding.mainContent.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
        @Override
        public void onViewAttachedToWindow(View view) {
            binding.toolbar.setPadding(binding.toolbar.getPaddingLeft(),
                binding.toolbar.getPaddingTop() + getStatusBarHeight(),
                binding.toolbar.getPaddingRight(), binding.toolbar.getPaddingBottom());
            binding.mainContent.removeOnAttachStateChangeListener(this);
        }

        @Override
        public void onViewDetachedFromWindow(View view) {

        }
    });

Ответ 11

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

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

Помните, что заполнение будет добавлено только к первому представлению в иерархии с fitSystemWindows, установленным в true

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

Эта статья хорошо читается на эту тему.