可靠获取状态栏高度解决KitKat半透明导航问题

Posted

技术标签:

【中文标题】可靠获取状态栏高度解决KitKat半透明导航问题【英文标题】:Reliably get height of status bar to solve KitKat translucent navigation issue 【发布时间】:2014-01-02 06:34:25 【问题描述】:

我正在试验新的 android 4.4 半透明导航栏,并希望使用 FLAG_TRANSLUCENT_NAVIGATION 标志将导航栏设置为半透明。我只希望导航栏(返回、主页按钮等)是半透明的 - 我希望屏幕顶部的状态栏正常显示,即不透明。

我用来实现这一点的代码是:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) 
    Window w = getWindow();
    w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

我遇到的问题是 Android 现在认为 Activity 是全屏的,并将布局放在导航栏后面(这是正确的),不幸的是它也将布局放在状态栏后面(有问题)。

对此的一个 hacky 解决方法是将填充应用到布局父视图的顶部,但是我需要确定状态栏的高度来执行此操作。

谁能建议我如何获得状态栏高度,它并不像我想象的那么简单,或者建议一个适当的解决方案。

谢谢

【问题讨论】:

嗨,Milo,我在这里遇到了同样的问题。我已经尝试过这种解决方法,但我的布局仍然落后于我的 ActionBAr。我在我的根布局中添加了一个顶部填充,但我认为状态栏高度不够,你有同样的问题吗?我需要为两个高度设置一个顶部填充? Noni,我得到Activity的根视图如下:getWindow().getDecorView().findViewById(android.R.id.content);然后我应用填充即setPadding(0, statusBarHeight, 0, 0);希望对您有所帮助。 【参考方案1】:
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 方法中使用上面的代码。将它放在 contextWrapper 类中。 http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/

【讨论】:

这似乎可行,您知道这是否适用于所有 Android 4.1 及更高版本?我记得读过这个解决方案可能不适用于 Transformer 平板电脑,这让我想知道这是否也会在其他设备上失败? 据我所知,它仅适用于变压器平板电脑。在我测试过的其他设备上运行良好。并且不要忘记接受和投票。欢呼 遗憾的是没有可靠的方法来获取每个设备上状态栏的高度。也就是说,现在必须这样做。 是的,只是因为它不能作为 API 的一部分公开提供给开发人员。它只是绕过它的一个技巧。希望下一个 SDK 版本会有官方支持。 只是补充一下,高度基本是25dip。我检查了来源。但是,指南给状态栏 24dp google.com/design/spec/layout/…【参考方案2】:

从 api 21 开始,有官方方法可以在半透明时检索状态栏和导航栏高度的插图

ViewCompat.setOnApplyWindowInsetsListener(view, new OnApplyWindowInsetsListener() 
        @Override
        public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) 
            final int statusBar = insets.getSystemWindowInsetTop();
            final int navigationBar = insets.getSystemWindowInsetBottom();
            return insets;
        
    );

【讨论】:

超级好用!在 Android 7.0 的多窗口模式下唯一能按预期工作的东西。 那种视图是“视图”? 我很想看到更多关于此的文档/信息。 getSystemWindowInsetTop() 似乎是“状态栏高度”的奇怪名称。 这有点棘手,因为 Google 假设状态栏并不总是在您的内容之上(还记得 Android Honeycomb UI 吗?)。导航栏也是如此 - 当您旋转屏幕时,它会出现在右侧。你不应该关心它们在哪里,系统会告诉你应该在哪里应用你的填充。在这里查看更多信息,阅读这篇文章:medium.com/google-developers/… 不知何故,onApplyWindowInsets() 在我的情况下没有被触发。我在片段的 onCreateView() 中设置了它。你有什么线索吗?【参考方案3】:

接受的答案总是返回状态栏高度(并且以一种有点老套的方式)。但有些活动实际上可能是全屏的,这种方法并不能区分它们。

这个方法非常适合我找到相对于当前活动的状态栏高度(将它放在你的 Activity 类中,并在布局完成后使用它):

public int getStatusBarHeight() 
    Rect displayRect = new Rect();
    getWindow().getDecorView().getWindowVisibleDisplayFrame(displayRect);
    return displayRect.top;

请注意,您也可以直接使用 displayRect,以防您在底部或什至可能是屏幕两侧有其他“窗口装饰”。

【讨论】:

这适用于 10.1 WXGA 表模拟器,它在 API 16 中不显示状态栏,因为它将状态信息放在底部导航栏中。仍在寻找一种方法来确定状态栏高度和/或显示状态之前布局。【参考方案4】:

建议使用此脚本获取状态栏高度

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

(旧方法)在你的Activity的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;

【讨论】:

以上是关于可靠获取状态栏高度解决KitKat半透明导航问题的主要内容,如果未能解决你的问题,请参考以下文章

android 4.4 的标签和半透明状态栏/导航出现问题

利用 Android 4.4 KitKat 中的半透明状态栏

利用 Android 4.4 KitKat 中的半透明状态栏

状态栏、导航栏、PopupWindow的使用

Android Kitkat 4.4版本状态栏下使用导航抽屉时状态栏颜色显示为白色不透明

ios导航栏半透明设置为NO改变底部UICollectionView的高度