状态栏的高度?

时间:2010-07-28 16:59:27

标签: android

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

我知道我们可以在初始布局传递之后得到它,但我希望在我的活动的onCreate()中得到它。

由于

13 个答案:

答案 0 :(得分:93)

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

答案 1 :(得分:39)

虽然这是一个老问题,但我发现答案在onCreate()中无效:

我发现here中的代码在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 :(得分:34)

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

repositories {
    maven {
        url "https://jitpack.io"
    }
}

不要被Android工作室弄糊涂(2.2预览3 - 在写作的那一刻)并不支持这个概念。运行时有。我是从Google的源代码中获取的。

答案 3 :(得分:7)

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

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

有关详细信息,我建议您查看Chris Banes的演讲 - 成为主窗口钳工(可用幻灯片here)。

答案 4 :(得分:6)

我建议下一个代码:

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 品牌:三星, 装置:maguro, 董事会:金枪鱼, cpu_abi:armeabi-v7a, 显示:ICL53F.M420KREL08, 制造商:三星, 型号: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 设备:bravo, 董事会:bravo, 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.

答案 5 :(得分:6)

您还可以使用this blog post描述的方式获取android的dimens.xml文件中找到的状态栏的维度。

这可以获得状态栏的高度,而无需等待绘图。

从博客文章中引用代码:

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类中。

答案 6 :(得分:5)

将onnable附加到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方法而不是post,并添加毫秒值作为第二个参数。

答案 7 :(得分:2)

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

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

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

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

答案 8 :(得分:1)

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

解决方案很简单 - 您应该将代码置于runnable中并使用root.post((Runnable action) );

在onCreate()之后执行它

所以整个解决方案:

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

我发现它here

答案 9 :(得分:1)

从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) {

        }
    });

答案 10 :(得分:1)

好的。最终答案!!!一种没有副作用,依赖于记录的行为,支持Q,保险开关,根据方向具有不同状态栏大小的设备&c。

protected void onCreate(Bundle savedInstanceState) {
     ...
     setContentView(R.layout.activity_main);
     ....
     // Use The topmost view of the activity, which 
    // is guaranteed to be asked about window insets/
     View rootView = findViewById(R.id.root_view_of_your_activity);
     ViewCompat.setOnApplyWindowInsetsListener(rootView, new OnApplyWindowInsetsListener() {
        @Override
        public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) 
    {
        //THIS is the value you want.
        statusBarHeight = insets.getSystemWindowInsetTop();

        // Let the view handle insets as it likes.
        return ViewCompat.onApplyWindowInsets(v,insets);
    }
});

回调发生在onStart()之后,第一个布局之前,偶尔在此之后。

答案 11 :(得分:0)

这似乎无关紧要,但在大多数情况下,人们寻找状态栏高度的原因是要偏移自己的视图,以便不将其置于其下方。

通过在要“下推”的视图上设置fitsSystemWindows,以在状态栏上留出空间,将根据每个设备上状态栏的大小自动完成此操作。填充将添加到该属性设置为true的视图中。

请记住,填充只会在fitSystemWindows设置为true的层次结构中添加到第一个视图中

例如,这适用于状态栏为半透明的情况。确保将主题设置为未设置fitSystemWindows的活动,否则填充将被添加到活动中(因为它是层次结构中的第一个)。

This article是有关该主题的好书

答案 12 :(得分:0)

针对 API 30,我已成功使用更新的 Nicklas 答案(参考:https://stackoverflow.com/a/47125610/2163045

在我的示例中,我在全屏 WindowCompat.setDecorFitsSystemWindows(window, false) Activity 中动态调整自定义工具栏高度

在 GooglePixel 5 上测试

class MyActivity : ViewBindingActivity<LayoutBinding>() {
...

    override fun created(binding: LayoutBinding, savedInstanceState: Bundle?) {

        binding.root.setOnApplyWindowInsetsListener { _, insets ->
            val statusBarHeight = insets.getInsets(WindowInsets.Type.statusBars()).top // <- HERE YOU ARE
            val toolbarHeight = getDimenPx(R.dimen.toolbar_height)
            binding.toolbar.layoutParams.height = statusBarHeight + toolbarHeight
            insets
        }
    }
}
相关问题