从 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 动态获取状态栏高度的主要内容,如果未能解决你的问题,请参考以下文章