Высота строки состояния в Android
Какова высота строки состояния в Android? Это всегда то же самое?
Из моих измерений кажется, что это 25dp, но я не уверен, что он имеет одинаковую высоту на всех платформах.
(Я хочу знать это, чтобы правильно реализовать переход с постепенным исчезновением из действия, которое не имеет строки состояния, к тому, которое имеет)
20 ответов
На этот вопрос ответили раньше... Высота строки состояния?
Обновление::
Текущий метод:
Хорошо, высота строки состояния зависит от размера экрана, например, в устройстве с размером экрана 240 x 320 высота строки состояния составляет 20 пикселей, для устройства с размером экрана 320 x 480 высота строки состояния составляет 25 пикселей, для для устройства с разрешением 480 x 800 высота строки состояния должна составлять 38 пикселей
поэтому я рекомендую использовать этот скрипт, чтобы получить высоту строки состояния
Rect rectangle = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
int statusBarHeight = rectangle.top;
int contentViewTop =
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight= contentViewTop - statusBarHeight;
Log.i("*** Elenasys :: ", "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;
}
Из всех примеров кода, которые я использовал, чтобы получить высоту строки состояния, единственный, который действительно работает в onCreate
метод Activity
это:
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Видимо, фактическая высота строки состояния сохраняется как ресурс Android. Приведенный выше код может быть добавлен в ContextWrapper
класс (например, Activity
).
Найдено по http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/
Жесткое кодирование размера или использование отражения для получения значения status_bar_height
считается плохой практикой. Крис Бейнс говорил об этом в Droidcon New York. Рекомендуемый способ получения размера строки состояния - через OnApplyWindowInsetsListener:
myView.setOnApplyWindowInsetsListener { view, insets -> {
val statusBarSize = insets.systemWindowInsetTop
return insets
}
Это было добавлено в API 20 и также портировано через ViewAppCompat.
На устройствах MDPI строка состояния составляет 25 пикселей. Мы можем использовать это в качестве основы и умножить на плотность (округлить в большую сторону), чтобы получить высоту строки состояния на любом устройстве:
int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);
Для справки: ldpi= 0,75, mdpi=1, hdpi=1,5, xhdpi=2
Я объединил некоторые решения вместе:
public static int getStatusBarHeight(final Context context) {
final Resources resources = context.getResources();
final int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
return resources.getDimensionPixelSize(resourceId);
else
return (int) Math.ceil((VERSION.SDK_INT >= VERSION_CODES.M ? 24 : 25) * resources.getDisplayMetrics().density);
}
другая альтернатива:
final View view = findViewById(android.R.id.content);
runJustBeforeBeingDrawn(view, new Runnable() {
@Override
public void run() {
int statusBarHeight = getResources().getDisplayMetrics().heightPixels - view.getMeasuredHeight();
}
});
РЕДАКТИРОВАТЬ: альтернатива runJustBeforeBeingDrawn: /questions/11647003/opredelenie-razmera-predstavleniya-android-vo-vremya-vyipolneniya/11647016#11647016
Согласно руководству по дизайну Google; высота строки состояния 24 дп.
Если вы хотите получить высоту строки состояния в пикселях, вы можете использовать метод ниже:
private static int statusBarHeight(android.content.res.Resources res) {
return (int) (24 * res.getDisplayMetrics().density);
}
который можно вызвать из активности с:
statusBarHeight(getResources());
Высота по умолчанию была 25dp. С Android Marshmallow (API 23) высота была уменьшена до 24dp.
Это также работает со ссылкой
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Официальный рост 24dp
, как официально заявлено Google на веб-странице Android Design.
Версия Kotlin, сочетающая в себе два лучших решения
fun getStatusBarHeight(): Int {
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
return if (resourceId > 0) resources.getDimensionPixelSize(resourceId)
else Rect().apply { window.decorView.getWindowVisibleDisplayFrame(this) }.top
}
- Берет
status_bar_height
значение, если присутствует - Если
status_bar_height
нет, вычисляет высоту строки состояния из Window decor
У меня та же проблема с необходимостью получить высоту строки состояния в onCreate. Это работает для меня.
private static final int LOW_DPI_STATUS_BAR_HEIGHT = 19;
private static final int MEDIUM_DPI_STATUS_BAR_HEIGHT = 25;
private static final int HIGH_DPI_STATUS_BAR_HEIGHT = 38;
Внутри onCreate:
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
int statusBarHeight;
switch (displayMetrics.densityDpi) {
case DisplayMetrics.DENSITY_HIGH:
statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT;
break;
case DisplayMetrics.DENSITY_MEDIUM:
statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
break;
case DisplayMetrics.DENSITY_LOW:
statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT;
break;
default:
statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
}
Увидеть:
http://developer.android.com/reference/android/util/DisplayMetrics.html http://developer.android.com/guide/practices/ui_guidelines/icon_design.html
Да, когда я пытаюсь сделать это с помощью View, он дает результат 25px. Вот весь код:
public class SpinActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout lySpin = new LinearLayout(this);
lySpin.setOrientation(LinearLayout.VERTICAL);
lySpin.post(new Runnable()
{
public void run()
{
Rect rect = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int contentViewTop =
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight = contentViewTop - statusBarHeight;
System.out.println("TitleBarHeight: " + titleBarHeight
+ ", StatusBarHeight: " + statusBarHeight);
}
}
}
}
Попробуй это:
Rect rect = new Rect();
Window win = this.getWindow();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight = contentViewTop - statusBarHeight;
Log.d("ID-ANDROID-CONTENT", "titleBarHeight = " + titleBarHeight );
он не работал для меня в методе onCreate для действия, но работал, когда я поместил его в onClickListener и дал мне измерение 25
Высота строки состояния в Android 6.0 24dp
<!-- Height of the status bar -->
<dimen name="status_bar_height">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
Вы можете найти ответ в исходном коде: frameworks\base\core\res\res\values \dimensions.xml
Чтобы решить эту проблему, я использовал комбинированный подход. Это необходимо, поскольку на планшетах системная панель уже вычитает свои пиксели при вызове display.getHeight(). Поэтому я сначала проверяю наличие системной панели, а затем подход Бена Клейтона, который отлично работает на телефонах.
public int getStatusBarHeight() {
int statusBarHeight = 0;
if (!hasOnScreenSystemBar()) {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
}
return statusBarHeight;
}
private boolean hasOnScreenSystemBar() {
Display display = getWindowManager().getDefaultDisplay();
int rawDisplayHeight = 0;
try {
Method getRawHeight = Display.class.getMethod("getRawHeight");
rawDisplayHeight = (Integer) getRawHeight.invoke(display);
} catch (Exception ex) {
}
int UIRequestedHeight = display.getHeight();
return rawDisplayHeight - UIRequestedHeight > 0;
}
Благодаря @Niklas +1 это правильный способ сделать это.
public class MyActivity extends Activity implements android.support.v4.View.OnApplyWindowInsetsListener {
Rect windowInsets;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
View rootview = findViewById(android.R.id.content);
android.support.v4.View.ViewCompat.setOnApplyWindowInsetsListener(rootview, this);
}
android.support.v4.View.WindowInsetsCompat android.support.v4.View.OnApplyWindowInsetsListener.OnApplyWindowInsets(View v, android.support.v4.View.WindowInsetsCompat insets)
{
windowInsets = new Rect();
windowInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
//StatusBarHeight = insets.getSystemWindowInsetTop();
//Refresh/Adjust view accordingly
return insets;
}
}
Пожалуйста, извините, если код не на 100% правильный, конвертируйте его из Xamarin C#, но это только его. Работает с надрезами и т. Д.
Поскольку сейчас доступен многооконный режим, ваше приложение может не иметь строки состояния вверху.
Следующее решение обрабатывает все случаи автоматически за вас.
android:fitsSystemWindows="true"
или программно
findViewById(R.id.your_root_view).setFitsSystemWindows(true);
вы также можете получить root-вид
findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)
Подробнее о получении root-view см. - /questions/41517683/poluchit-kornevoj-vid-iz-tekuschej-aktivnosti/41517688#41517688
Toggled Fullscreen Solution:
Это решение может выглядеть как обходной путь, но на самом деле оно учитывает, является ли ваше приложение полноэкранным (то есть скрывающим строку состояния) или нет:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int barheight = size.y - findViewById(R.id.rootView).getHeight();
Таким образом, если ваше приложение в настоящее время полноэкранное, barheight
будет равно 0.
Лично мне пришлось использовать это, чтобы исправить абсолютные координаты TouchEvent, чтобы учесть статусную строку следующим образом:
@Override
public boolean onTouch(View view,MotionEvent event) {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int YCoord = (int)event.getRawY() - size.y + rootView.getHeight());
}
И это получит абсолютную Y-координату, будет ли приложение полноэкранным или нет.
наслаждаться
В Android 4.1 и более поздних версиях вы можете настроить отображение содержимого приложения за строкой состояния, чтобы содержимое не изменялось, поскольку строка состояния скрывается и отображается. Для этого используйте SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN. Вам также может понадобиться использовать SYSTEM_UI_FLAG_LAYOUT_STABLE, чтобы помочь вашему приложению поддерживать стабильный макет.
Когда вы используете этот подход, вы несете ответственность за то, чтобы критические части пользовательского интерфейса вашего приложения (например, встроенные элементы управления в приложении Maps) не покрывались системными панелями. Это может сделать ваше приложение непригодным для использования. В большинстве случаев вы можете справиться с этим, добавив атрибут android:fitsSystemWindows в файл макета XML, установив значение true. Это регулирует заполнение родительской ViewGroup, чтобы оставить место для системных окон. Этого достаточно для большинства приложений.
Однако в некоторых случаях вам может потребоваться изменить отступы по умолчанию, чтобы получить желаемый макет для вашего приложения. Чтобы напрямую манипулировать расположением вашего контента относительно системных панелей (занимающих пространство, известное как "вставки содержимого" окна), переопределите fitSystemWindows(вставки Rect). Метод fitSystemWindows() вызывается иерархией представления, когда вставки содержимого для окна изменились, чтобы позволить окну соответствующим образом корректировать свое содержимое. Переопределив этот метод, вы можете обрабатывать вставки (и, следовательно, макет вашего приложения), как хотите.
форма: https://developer.android.com/training/system-ui/status.html
Причина, по которой верхний ответ не работает для некоторых людей, заключается в том, что вы не можете получить размеры представления, пока оно не будет готово к визуализации. Используйте OnGlobalLayoutListener
чтобы получить указанные размеры, когда вы действительно можете:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
// Nice one, Google
decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Rect rect = new Rect();
decorView.getWindowVisibleDisplayFrame(rect);
rect.top; // This is the height of the status bar
}
}
}
Это самый надежный метод.
Если вы точно знаете размер VS высота
лайк
например, в устройстве с размером экрана 320 x 480 высота строки состояния составляет 25 пикселей, для устройства с разрешением 480 x 800 высота строки состояния должна составлять 38 пикселей.
тогда вы можете просто получить ширину вашего вида / размер экрана, вы можете просто использовать оператор if else, чтобы получить высоту строки состояния
Этот вопрос недавно стал актуальным для меня из-за выемки в моем Pixel 3XL. Мне очень понравилось решение для разработчиков Android, но я хотел иметь возможность получить высоту строки состояния по своему желанию, поскольку это было особенно необходимо для полноэкранной анимации, которую мне нужно было воспроизвести. Функция ниже включила надежный запрос:
private val DEFAULT_INSET = 96
fun getInsets(view: View?): Int {
var inset = DEFAULT_INSET
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Safe because only P supports notches
inset = view?.rootWindowInsets?.stableInsetTop ?: DEFAULT_INSET
}
return inset
}
Протестированный код для получения высоты строки состояния (в пикселях):
public static int getStatusBarHeight(Context c) {
int resourceId = c.getResources()
.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
return c.getResources().getDimensionPixelSize(resourceId);
}
return 0;
}
Протестированный код для получения высоты навигационной панели (в пикселях):
public static int getNavBarHeight(Context c) {
int resourceId = c.getResources()
.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
return c.getResources().getDimensionPixelSize(resourceId);
}
return 0;
}
Преобразование пикселей в dp:
public static int pxToDp(int px) {
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}