Android中状态栏的高度是多少?

从我的测量来看,好像是25dp,但是我不确定在所有平台上它的高度是否都一样。

(我要知道这一点以正确实现从没有状态栏的活动到有状态栏的活动的淡入淡出过渡)

评论

如果进行交叉淡入淡出,则无需知道状态栏的高度。

我确实需要它,因为有些元素在布局中居中,我希望它们彼此淡入。

#1 楼

此问题在...之前被回答过...
状态栏的高度?

更新::

当前方法:

好,高度状态栏的大小取决于屏幕尺寸,例如,在屏幕尺寸为240 X 320的设备中,状态栏高度为20px,对于屏幕尺寸为320 X 480的设备,状态栏高度为25px,对于480 x 800的设备,状态栏的高度必须为38px

,所以我建议使用此脚本获取状态栏的高度

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


评论


不完全是。我还问我是否可以假设状态栏在所有设备中都具有相同的高度。

–hpique
2010年8月4日在22:19

还是用蘸酱?如果始终为25dip,则不需要代码。

–hpique
10年8月6日在12:08

您不能假设它始终为25dp(例如,检查点燃时的高度)。

–DallinDyer
2012年1月18日23:12

在onCreate()中传递给view.post()的runnable中不起作用-返回0

– Ixx
13年4月19日在20:24

如果您处于多窗口模式+纵向旋转+第二个窗口,则window.getDecorView()。getWindowVisibleDisplayFrame(rectangle)不是获取状态栏高度的正确方法。您将获得巨大的价值(包括第一高度)。

–团洲
18年6月7日在7:40

#2 楼

在我用来获取状态栏高度的所有代码示例中,唯一真正在onCreateActivity方法中起作用的代码示例是:

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 /

评论


与其进行硬编码,不如进行动态计算。上面的方法对我有用!

–炼金术士
13年7月5日在7:20

您不应该使用getDimension(...)代替吗?

– Android开发人员
13年19月19日在15:04

请注意-并非在所有设备上都适用。例如。在Transformer TF201(以及TF101,TF300和某些其他设备)上,高度报告为25,其中没有状态栏。

–BłażejCzapp
13年11月28日在12:15

基于上面的评论,在我看来,代码告诉您特定设备上状态栏的高度,而不是特定活动(实际上可能没有状态栏)上的高度。

–茫然
15年12月15日在13:04

在XML中,可以使用dimen资源“ @android:dimen / status_bar_height”。 <!-在Android系统源文件中定义的状态栏的高度-> 24dp 。但是您不能在应用程序项目中直接引用它。因此,您必须使用代码。

– Tungunglee
18/12/12在6:45



#3 楼

硬编码大小或使用反射获得status_bar_height的值被认为是不良做法。克里斯·班尼斯(Chris Banes)在纽约Droidcon大会上谈到了这一点。推荐的获取状态栏大小的方法是通过OnApplyWindowInsetsListener:

myView.setOnApplyWindowInsetsListener { view, insets -> {
  val statusBarSize = insets.systemWindowInsetTop
  return insets
}


这是在API 20中添加的,也通过ViewAppCompat向后移植。

评论


这是今天最准确的答案

–基思
18年2月5日在21:46

对我来说,这只会触发一次,如果我通过底部导航有碎片。如果我再次替换该片段,则不会调用此侦听器,是否还有兼容的吸气剂?

–urSus
18 Mar 11 '18 at 2:51

但是这个API太可怕了,因为幕后的WTF / Gotchas数量巨大。您以为可以在任何视图中进行操作,但是不可以,您需要重写某些内容并确保将插图传递给孩子(??),因为某些ViewGroup(材料设计)会(其他设计)不会(线性布局?ConstraintLayout?你好?)。而不是拥有Window.getStatusBarSize()的系统……我们必须订阅一个令人讨厌的听众……回到Android,你醉了。只是硬编码大小,直到Google醒来,我们就在2018年。我希望克里斯·巴内斯(Chris Banes)看到这一天……

– Martin Marconcini
18 Jun 19'在20:49



就我而言,它没有被解雇。我把它叫做Activity#onCreated。我做错什么了吗?另外,为什么不使用mView.getRootWindowInsets()?

–阿迪尔·阿里耶夫(Adil Aliyev)
18-10-26在7:00

#4 楼

在MDPI设备上,状态栏为25px。我们可以将其用作基础并乘以密度(向上舍入)以获取任何设备上状态栏的高度:

int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);


作为参考:ldpi =。 75,mdpi = 1,hdpi = 1.5,xhdpi = 2

评论


这对于具有状态栏的设备是正确的。请注意,自从以上内容编写以来,并非所有设备都拥有一个设备,这是事实。具体来说,运行ICS的设备可能在底部具有组合的状态/导航栏,而在顶部则完全没有。因此,在这种情况下,出于大多数编程目的,您希望将状态栏的高度设置为零,但是上述公式将为您提供非零的大小。

–卡尔
2012年12月12日5:11



同样,25px值对于所有mdpi设备也不正确。它可以根据API级别而有所不同。例如,10.1 WXGA平板电脑仿真器设备在API 16和19处报告25px,在API 24处报告24px。

– jk7
17年7月26日在20:33

#5 楼

我已经合并了一些解决方案:

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


另一个选择: :https://stackoverflow.com/a/28136027/878126

评论


getResources()。getDisplayMetrics()。heightPixels -getActivity()。findViewById(android.R.id.content).getMeasuredHeight()在android lolipop中不起作用

– abbasalim
2015年9月2日于10:08



@ ArMo372更新了答案。只是视图需要首先通过度量。如果已经传递过runJustBeforeBeingDrawn,则无需使用它。您只会在过早的情况下使用它。

– Android开发人员
16年8月15日在19:17

#6 楼

根据Google设计指南;状态栏的高度为24 dp。

如果要获取状态栏的高度(以像素为单位),可以使用以下方法:

private static int statusBarHeight(android.content.res.Resources res) {
    return (int) (24 * res.getDisplayMetrics().density);
}

通过以下活动被调用:

statusBarHeight(getResources());


评论


直到棉花糖是25dp。自棉花糖以来24dp。

– Eugen Pechanec
2015年9月17日下午21:46

这实质上是对值进行硬编码-不允许进行设计更改

–siliconeagle
17年6月28日在16:04

并且不考虑在相同情况下不会显示状态栏的事实

– jk7
17年7月26日在20:36

#7 楼

默认高度为25dp。使用Android棉花糖(API 23)时,高度降低到24dp。更长的作品。请改用窗口插图!

评论


甜!我刚刚专门为API级别23+创建了dimens.xml,在其中我已将高度硬编码为24dp。

–某处有人
18年4月19日在17:22

#8 楼

这也适用于参考链接

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


#9 楼

官方高度是24dp
由Google在Android设计网页上正式声明。

#10 楼

我有一个必须在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

评论


我喜欢您使用密度驱动值的想法。如果您打算在多个位置使用代码(或使用其他与密度相关的值),则我更喜欢将工作卸载到系统中,并将这些值存储在dimen资源中,这使得无需进行切换。您确实需要为每个密度创建一个特定于维度的文件夹和资源文件。最终资源res = context.getResources(); int statusbarHeight = 0;尝试{statusbarHeight = res.getDimensionPixelSize(R.dimen.android_statusbar_height); } catch(NotFoundException e){}

–ProjectJourneyman
2011-12-13 19:16



对这些值进行硬编码很危险,如果它们在更高的平台版本中更改,该怎么办?

– David Snabel-Caunt
2012年2月22日15:34

我认为与其使用硬编码的像素大小(每个密度一个),不如使用“ 25dp”。

– Android开发人员
2015年3月10日14:04



#11 楼

是的,当我尝试使用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);
            }
        }
    }
}


评论


当我像上面所做的那样创建新的线性布局时,但是当我从xml找到lySpin的findviewbyid时,上面的代码对我有用。然后返回null。不了解你的行为。

– Shaista Naaz
11年6月23日在17:06

因为布局尚未在onCreate中知道其大小,因为尚未完成绘制。我通常要做的是在onCreate上的UI线程上发布一个Runnable,它使UI有时间进行绘制。

–詹森·罗宾逊(Jason Robinson)
2012年1月18日在0:00

#12 楼


240x320-20像素
320x480-25像素

评论


这不再准确。使用一种测量状态栏的方法。

–迈克尔
19年1月3日,16:22

#13 楼

试试这个:

    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

评论


我怀疑在他在onCreate()上进行测试时,状态栏尚未创建。相反,当他手动单击以激活他的onClickListener()代码时,该条已经有足够的思考时间来显示,并且他能够检索其大小。

–卡尔
2012年5月26日上午11:40

#14 楼

状态栏的高度在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 \ res \ values \ dimens.xml

评论


有没有办法在我们的XML中获取此资源? @android:dimen / status_bar_height对我不起作用

–avalancha
20-04-17在12:02

#15 楼

为了解决这个问题,我使用了一种组合方法。
这是必要的,因为在平板电脑上,调用display.getHeight()时,系统栏已经减去了像素。
所以我首先检查是否存在系统栏。 ,然后采用Ben Claytons的方法,这种方法在手机上效果很好。

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


#16 楼

感谢@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#转换而来但这仅仅是正义。适用于缺口等。

#17 楼

切换全屏解决方案:

该解决方案看起来像是一种解决方法,但实际上它说明了您的应用是否为全屏(也就是隐藏状态栏):

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键盘时唯一适用于我的解决方案。

– Thiago Moura
16年8月25日在16:50

#18 楼

在Android 4.1及更高版本上,您可以将应用程序的内容设置为显示在状态栏的后面,以使内容不会随着状态栏的隐藏和显示而改变大小。为此,请使用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN。您可能还需要使用SYSTEM_UI_FLAG_LAYOUT_STABLE来帮助您的应用维持稳定的布局。

,当您使用这种方法时,有责任确保应用UI的关键部分(例如,在Maps应用程序的控件中)不会最终被系统栏覆盖。这可能会使您的应用无法使用。在大多数情况下,您可以通过将android:fitsSystemWindows属性添加到XML布局文件(设置为true)来处理此问题。这将调整父ViewGroup的填充以为系统窗口留出空间。这对于大多数应用程序来说已经足够。

但是,在某些情况下,您可能需要修改默认填充以获取所需的应用程序布局。要直接操纵内容相对于系统栏的布局方式(系统栏占据着一个窗口的“内容插图”),请覆盖fitSystemWindows(Rect插图)。当窗口的内容插入发生更改时,视图层次结构将调用fitSystemWindows()方法,以允许窗口相应地调整其内容。通过覆盖此方法,您可以根据需要处理插入(以及应用布局)。

形式:
https://developer.android.com/training/system-ui/ status.html#behind

#19 楼

结合了两个最佳解决方案的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计算状态栏的高度装饰


#20 楼

如果您确切知道VS高度的大小



,例如在屏幕尺寸为320 X 480的设备中,对于480 x 800的设备,状态栏的高度为25px状态栏的高度必须为38px

,那么您只需要获取视图的宽度/屏幕尺寸,就可以使用if else语句获取状态栏的高度

评论


以我的经验,高度似乎是基于密度而不是屏幕尺寸。当然,密度本身通常与屏幕尺寸有关,因此存在间接关系。例如,我的旧版Moto Droid具有480x854(而不是480x800)显示屏,并且状态栏也高38像素。

–卡尔
2012年5月26日下午22:00

他们为此发明了dp(与密度无关的像素)

– Roel
14-10-29在12:29

#21 楼

最佳答案对某些人不起作用的原因是,在准备好渲染视图之前,您无法获得视图的尺寸。实际使用时,请使用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
        }
    }
}


这是最可靠的方法。

评论


@androiddeveloper OnGlobal!= GlobalOn

–marijnz0r
16年8月18日在14:02

@ marijnz0r多么奇怪。怎么办?

– Android开发人员
16年8月18日在20:24

@androiddeveloper我不知道,但是我碰巧也和几天前一样。请参阅:stackoverflow.com/a/19216041/4587214

–marijnz0r
16年8月19日在14:36

@ marijnz0r所以两者都一样。让我想起了其他情况,他们为已经存在的东西命名了一个新名称,并弃用了前一个。示例“ fill_parent”和“ match_parent”:developer.android.com/reference/android/view/…

– Android开发人员
16年8月19日在21:14

#22 楼

由于现在可以使用多窗口模式,因此您的应用程序顶部可能没有状态栏。

以下解决方案将自动为您处理所有情况。

android:fitsSystemWindows="true"

< br或以编程方式

findViewById(R.id.your_root_view).setFitsSystemWindows(true);


您还可以通过

findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)

获得根视图

有关更多详细信息获取root-view参考-https://stackoverflow.com/a/4488149/9640177

#23 楼

由于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
}

fun blurView(rootView: View?, a: SpacesActivity?) {
    val screenBitmap = getBitmapFromView(rootView!!)
    val heightDifference = getInsets(rootView)
    val croppedMap = Bitmap.createBitmap(
                    screenBitmap, 0, heightDifference,
                    screenBitmap.width,
                    screenBitmap.height - heightDifference)
    val blurredScreen = blurBitmap(croppedMap)
    if (blurredScreen != null) {
         val myDrawable = BitmapDrawable(a!!.resources, blurredScreen)
         a.errorHudFrameLayout?.background = myDrawable
         a.appBarLayout?.visibility = View.INVISIBLE
   }
}


,然后在活动类中:

fun blurView() {
    this.runOnUiThread {
        Helper.blurView(this)
    }
}


您当然,我想将活动的弱引用传递给静态Helper类方法参数,但是为了简洁起见,在本示例中,我将其省略。出于相同的原因,省略了blurBitmaperrorHudFrameLayout,因为它们与获取状态栏的高度不直接相关。

评论


如果适用于Android P及更高版本,为什么还要使用Android M?另外,如果没有View实例,该怎么办?例如,如果您当前没有活动...

– Android开发人员
18/12/5在10:07

M是最早可以检查stableInsetTop的方法,即使只支持P支持的槽口,我还是希望获得实际的插入量,而不是回到我可以的默认位置。如果您没有任何活动,则此解决方案不起作用。

–詹姆斯·乔丹·泰勒(James Jordan Taylor)
18/12/5在18:19

我懂了。谢谢。您能否显示一个更“完整”的示例?

– Android开发人员
18/12/5在18:29

我将上面的答案更改为在示例中使用该方法。

–詹姆斯·乔丹·泰勒(James Jordan Taylor)
18/12/9在17:15