Высота статусной панели?
Есть ли способ получить высоту строки состояния + заголовок? Проверка форума 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
, в противном случае вместо него будет добавлено заполнение (поскольку оно является первым в иерархии).
Эта статья хорошо читается на эту тему.