从 XML 动态获取状态栏高度

Posted

技术标签:

【中文标题】从 XML 动态获取状态栏高度【英文标题】:Get status bar height dynamically from XML 【发布时间】:2018-08-16 16:49:20 【问题描述】:

我需要优化我的 android 应用,使其在带有刘海屏的手机(例如 Essential Phone)上看起来不错。

这款手机的状态栏高度与标准 25dp 值不同,因此您无法对该值进行硬编码。

昨天发布的 Android P 开发者预览版包括对缺口的支持和一些 API 来查询其位置和边界,但对于我的应用程序,我只需要能够从 XML 中获取状态栏高度,而不是使用固定值.

不幸的是,我找不到从 XML 获取该值的任何方法。

有什么办法吗?

谢谢。

【问题讨论】:

@skotos 的回答对我有用 【参考方案1】:

我已经found the answer:

推荐的方法是使用 WindowInsets API,如下所示:

view.setOnApplyWindowInsetsListener  v, insets -> 
    view.height = insets.systemWindowInsetTop // status bar height
    insets

强烈建议不要访问 status_bar_height,因为它是私有资源,因此可能会在未来的 Android 版本中发生变化。

【讨论】:

从 xml 询问操作。在 ios 上有“安全”的布局指南。【参考方案2】:

这不是一个解决方案,但它可以向您解释应该如何以正确的方式使用它以及事情是如何进行的: https://www.youtube.com/watch?v=_mGDMVRO3iE

旧解决方案:

这是一个小技巧:

@*android:dimen/status_bar_height

android studio 会显示一个错误,但它会像魅力一样工作:)

【讨论】:

您的构建可能会在任何稍微现代的构建工具版本上失败,并显示“错误:资源 android:dimen/status_bar_height 是私有的。”。 @NPike 不。有用。但我同意这绝对不是最好的解决方案...... @AndriyAntonov 没有构建错误,在 android N,O 上运行良好,但在 P 上没有 这在一个 Google Pixel 上对我有用,但在另一个具有完全相同的操作系统的情况下,发布版本在其上崩溃。不幸的是,这个解决方案似乎不可靠,不应该使用。 :(【参考方案3】:

方法提供状态栏的高度

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

【讨论】:

这很好用。正在使用 Zoom SDK,他们已经在他们的 SDK 中声明了这个确切的功能,只是有点不同 - if(resourceId < 0) result = 25.0f * context.getResources().getDisplayMetrics().density + 0.5F;。如果没有像某些三星设备那样找到 resourceId,这将有所帮助。【参考方案4】:
class StatusBarSpacer @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
View(context, attrs) 
private var statusHeight: Int = 60

init 
    if (context is Activity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) 
        context.window.decorView.setOnApplyWindowInsetsListener  _, insets ->
            statusHeight = insets.systemWindowInsetTop
            requestLayout()
            insets
        
        context.window.decorView.requestApplyInsets()
     else statusHeight = resources.getDimensionPixelSize(
        resources.getIdentifier("status_bar_height", "dimen", "android")
    )


override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) =
    setMeasuredDimension(0, statusHeight)

【讨论】:

【参考方案5】:

我找到了一种使用状态栏大小的解决方案,它应该适合任何设备。这是一种将大小从代码转换为 XML 布局的方法。

解决方案是创建一个根据状态栏大小自动调整大小的视图。它就像约束布局的指南。

我确信它应该是一个更好的方法,但我没有找到它。如果您考虑改进此代码,请现在告诉我:

科特林

class StatusBarSizeView: View 

companion object 

    // status bar saved size
    var heightSize: Int = 0


constructor(context: Context):
        super(context) 
    this.init()


constructor(context: Context, attrs: AttributeSet?):
        super(context, attrs) 
    this.init()


constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int):
        super(context, attrs, defStyleAttr) 
    this.init()


private fun init() 

    // do nothing if we already have the size
    if (heightSize != 0) 
        return
    

    // listen to get the height
    (context as? Activity)?.window?.decorView?.setOnApplyWindowInsetsListener  _, windowInsets ->

        // get the size
        heightSize = windowInsets.systemWindowInsetTop

        // return insets
        windowInsets
    



override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) 
    super.onSizeChanged(w, h, oldw, oldh)

    // if height is not zero height is ok
    if (h != 0 || heightSize == 0) 
        return
    

    // apply the size
    postDelayed(Runnable 
        applyHeight(heightSize)
    , 0)


private fun applyHeight(height: Int) 

    // apply the status bar height to the height of the view
    val lp = this.layoutParams
    lp.height = height
    this.layoutParams = lp



那么你可以在 XML 中使用它作为指南:

<com.foo.StatusBarSizeView
        android:id="@+id/fooBarSizeView"
        android:layout_
        android:layout_ />

“heightSize”变量是公开的,如果某些视图需要它,可以在代码中使用它。

也许它对其他人有帮助。

【讨论】:

以上是关于从 XML 动态获取状态栏高度的主要内容,如果未能解决你的问题,请参考以下文章

iOS 13后状态栏获取高度的方法

Android获取状态栏和标题栏的高度

iOS - 14、15 iPhone苹果手机的状态栏高度

iOS 14、15苹果手机状态栏高度

Flutter:从 AppBar 中减去状态栏高度

android状态栏高度是多少