Android 状态栏的高度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3355367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:52:10  来源:igfitidea点击:

Height of statusbar?

android

提问by user291701

Is there a way to get the height of the statusbar + titlebar? Checking the dev forum shows the same question but no solution (that I could find).

有没有办法获取状态栏+标题栏的高度?检查开发论坛显示了相同的问题,但没有解决方案(我能找到)。

I know we can get it after the initial layout pass, but I'm looking to get it in onCreate() of my activity.

我知道我们可以在初始布局通过后获得它,但我希望在我的活动的 onCreate() 中获得它。

Thanks

谢谢

回答by Jorgesys

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

Get the Height of the status bar on the onCreate()method of your Activity, use this method:

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

回答by Aleksey Gureiev

For those, like me, who want to use it in your XML layouts:

对于像我这样想在 XML 布局中使用它的人:

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

Don't be confused by that Android Studio (2.2 Preview 3 -- at the moment of writing) doesn't support this notion. The runtime does. I took it from the Google's source code.

不要被 Android Studio(2.2 预览版 3——在撰写本文时)不支持这个概念所迷惑。运行时确实如此。我从谷歌的源代码中获取了它。

回答by raukodraug

Although this is an old question, I found that the answer didn't work in onCreate():

虽然这是一个老问题,但我发现答案在onCreate()以下情况下不起作用:

I found this code from herewhich does work in the onCreate()method

我从这里找到了这段代码,它在该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;
}

I hope this helps to anyone that runs into this issue.

我希望这对遇到此问题的任何人都有帮助。

回答by yarq

The supported way of getting status bar height is to use WindowInsetsclass starting from API 21+:

支持的获取状态栏高度的方法是使用WindowInsets从 API 21+ 开始的类:

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

or WindowInsetsCompatfor support libraries:

WindowInsetsCompat支持库:

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

You can also override the onApplyWindowInsetsmethod inside the view:

您还可以覆盖onApplyWindowInsets视图内的方法:

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

For further details, I'd recommend checking Chris Banes talk - Becoming a master window fitter(slides available here).

有关更多详细信息,我建议您查看 Chris Banes 谈话 - Becoming a master window fitter此处提供幻灯片)。

回答by dvpublic

I would suggest next code:

我建议下一个代码:

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

Two examples:

两个例子:

1) Device 1 brand: samsung, device: maguro, board: tuna, cpu_abi: armeabi-v7a, display: ICL53F.M420KREL08, manufacturer: samsung, model: Galaxy Nexus, ver.release: 4.0.2, ver.sdk: 14;

1) 设备 1 品牌:samsung,设备:maguro,主板:tuna,cpu_abi:armeabi-v7a,显示器:ICL53F.M420KREL08,制造商:samsung,型号:Galaxy Nexus,ver.release:4.0.2,ver.sdk:14 ;

Screen resolution: 1280 x 720.There are no hardware buttons on this device.

屏幕分辨率:1280 x 720。此设备上没有硬件按钮。

Results:

结果:

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;

Device 1 has title bar at the top of the screen and status bar with software buttons at the bottom of the screen.

设备 1 在屏幕顶部有标题栏,在屏幕底部有带有软件按钮的状态栏。

2) Device 2 device: bravo, board: bravo, cpu_abi: armeabi-v7a, display: FRG83G, manufacturer: HTC, model: HTC Desire, ver.release: 2.2.2, ver.sdk: 8,

2) Device 2 device: bravo, board: bravo, cpu_abi: armeabi-v7a, display: FRG83G, 厂商: HTC, 型号: HTC Desire, ver.release: 2.2.2, ver.sdk: 8,

Screen resolution: 800 x 400. This device has hardware buttons.

屏幕分辨率:800 x 400。此设备具有硬件按钮。

Results:

结果:

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;

Device 2 has title bar at the top of the screen and hasn't status bar at all.

设备 2 在屏幕顶部有标题栏,根本没有状态栏。

Two solutions were suggested above:

上面提出了两种解决方案:

A) v.getTop() - rect.top 

(it is incorrect for device 1- it gives 0 instead of 72)

设备 1 不正确- 它给出 0 而不是 72)

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

(it is incorrect for device 2- it gives 0 instead of 38)

设备 2 不正确- 它给出 0 而不是 38)

Variant:

变体:

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

gives correct results in both cases.

在这两种情况下都给出正确的结果。

Update

更新

3) One more example (third device): brand: LGE, device: v909, cpu_abi: armeabi-v7a, display: HMJ37, model: LG-V909, ver.release: 3.1, ver.sdk: 12

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

Device 3 has horizontal orientation, hasn't title bar at the top of the screen and has status bar at the bottom of the screen.

设备 3 为水平方向,屏幕顶部没有标题栏,屏幕底部有状态栏。

So, here:

所以在这里:

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

It's correct for devices 2 and 3. I am not sure about device 1. User sent me screenshot of device 1. There is a status bar with software button there. But expression "display.getHeight() - v.getBottom()" gives 0.

它适用于设备 2 和 3。我不确定设备 1。用户给我发送了设备 1 的屏幕截图。那里有一个带有软件按钮的状态栏。但是表达式“display.getHeight() - v.getBottom()”给出0。

回答by LKallipo

You could also take the dimension of the status bar found in the dimens.xml file of android using the way that this blog postdescribes.

您还可以使用此博客文章描述的方式获取在 android 的 dimens.xml 文件中找到的状态栏的尺寸。

This can get the height of the statusbar without the need to wait for drawing.

这样就可以获取状态栏的高度,而无需等待绘制。

Quoting the code from the blog post:

引用博文中的代码:

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

You need to put this method in a ContextWrapper class.

您需要将此方法放在 ContextWrapper 类中。

回答by Kachi

Attach a runnable to one of your views in your onCreate method, and place the above code in there. This will cause the application to calculate the status bar + titlescreen height when they are attached to the screen.

在您的 onCreate 方法中将一个 runnable 附加到您的一个视图,并将上面的代码放在那里。这将导致应用程序在附加到屏幕时计算状态栏 + 标题屏幕高度。

Take a look at the code below:

看看下面的代码:

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;

        }

    });

If this still doesn't do the trick, try invoking the view's postDelayed method instead of post and adding a millisecond value as the second argument.

如果这仍然不能解决问题,请尝试调用视图的 postDelayed 方法而不是 post 并添加一个毫秒值作为第二个参数。

回答by Mikooos

I think better way to calculate that is to get height of fullscreen minus our main layout

我认为更好的计算方法是获得全屏高度减去我们的主要布局

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

And you can put it in onGlobalLayout(). This works on tablets too, I tried it on Theme.NoTitleBar, but it must always works.

你可以把它放进去onGlobalLayout()。这也适用于平板电脑,我在 Theme.NoTitleBar 上尝试过,但它必须始终有效。

Maybe you can even enhance it and use it onCreate()by changing mainView.getHeight()to mainView.getMeasuredHeight().

也许您甚至可以onCreate()通过更改mainView.getHeight()为 来增强它并使用它mainView.getMeasuredHeight()

回答by jakkubu

The solution posted by Jorgesys is very good, but it doesn't work inside onCreate() method. I guess it's because statusbar and titlebar are created after onCreate().

Jorgesys 发布的解决方案非常好,但它在 onCreate() 方法中不起作用。我猜这是因为状态栏和标题栏是在 onCreate() 之后创建的。

The solution is easy - you should put code inside runnable and execute it after onCreate() by using root.post((Runnable action) );

解决方案很简单 - 您应该将代码放入 runnable 并在 onCreate() 之后使用 root.post((Runnable action) );

So the whole solution:

所以整个解决方案:

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

I find it here

我在这里找到

回答by Clyde

As of API 23 there is a better solution to getting the status bar height. API 23 adds a WindowInsetsfeature, so you can use this code to get the size of the system insets, in this case at the top.

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

Note that getRootWindowInsets()will return null until after the View has been attached to a Window so it can't be used directly in onCreate()but you can add a listener for the window attach and do it there - here I am adding the status bar inset to the size of my toolbar, which I hide and show, along with the status bar. When it's shown, I want the status bar over the top of it so I add the status bar height to the toolbar's top padding.

请注意,getRootWindowInsets()在 View 附加到 Window 之前将返回 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) {

        }
    });