从XML动态获取状态栏高度

时间:2018-03-08 10:51:22

标签: android android-layout

我需要优化我的Android应用,以便在具有缺陷的手机上看起来很好,例如Essential Phone。

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

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

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

有什么办法吗?

谢谢。

5 个答案:

答案 0 :(得分:7)

我已经found the answer

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

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

非常不鼓励访问status_bar_height,因为它是私有资源,因此可能会在未来版本的Android中发生变化。

答案 1 :(得分:3)

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

答案 2 :(得分:2)

方法提供状态栏的高度

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

答案 3 :(得分:2)

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

OLD SOLUTION:

这是一个小技巧:

@*android:dimen/status_bar_height

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

答案 4 :(得分:0)

我找到了一种解决方案,可以使用适合任何设备的状态栏大小。这是一种将大小从代码转换为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_width="match_parent"
        android:layout_height="0dp" />

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

也许对其他人有帮助。