Android中状态栏的高度是多少?它总是一样吗?
从我的测量来看,它似乎是 25dp,但我不确定它是否在所有平台上都具有相同的高度。
(我想知道这一点以正确实现从没有状态栏的活动到有状态栏的活动的淡入淡出过渡)
之前回答过这个问题...... 状态栏的高度?
更新::
好的,状态栏的高度取决于屏幕尺寸,例如在屏幕尺寸为 240 X 320 的设备中,状态栏高度为 20px,对于屏幕尺寸为 320 X 480 的设备,状态栏高度为 25px,对于480 x 800 的设备状态栏高度必须为 38px
所以我建议使用这个脚本来获取状态栏高度
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);
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;
}
在我用来获取状态栏高度的所有代码示例中,唯一真正看起来可以在onCreate
an 方法中工作的Activity
是:
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
显然,状态栏的实际高度被保存为 Android 资源。上面的代码可以添加到一个ContextWrapper
类(例如一个Activity
)。
发现于http://mrtn.me/blog/2012/03/17/get-the-height-of-the-status-bar-in-android/
硬编码大小或使用反射来获取值status_bar_height
被认为是不好的做法。Chris Banes在纽约 Droidcon 上谈到了这一点。获取状态栏大小的推荐方法是通过OnApplyWindowInsetsListener:
myView.setOnApplyWindowInsetsListener { view, insets -> {
val statusBarSize = insets.systemWindowInsetTop
return insets
}
这是在 API 20 中添加的,并且也通过ViewAppCompat向后移植。
在 MDPI 设备上,状态栏为 25px。我们可以使用它作为基础并将其乘以密度(向上取整)以获得任何设备上的状态栏高度:
int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);
供参考:ldpi=.75, mdpi=1, hdpi=1.5, xhdpi=2
我将一些解决方案合并在一起:
public static int getStatusBarHeight(final Context context) {
final Resources resources = context.getResources();
final int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
return resources.getDimensionPixelSize(resourceId);
else
return (int) Math.ceil((VERSION.SDK_INT >= VERSION_CODES.M ? 24 : 25) * resources.getDisplayMetrics().density);
}
另一种选择:
final View view = findViewById(android.R.id.content);
runJustBeforeBeingDrawn(view, new Runnable() {
@Override
public void run() {
int statusBarHeight = getResources().getDisplayMetrics().heightPixels - view.getMeasuredHeight();
}
});
编辑:替代 runJustBeforeBeingDrawn:https ://stackoverflow.com/a/28136027/878126
根据材料指南;状态栏的高度为 24 dp。
如果要以像素为单位获取状态栏高度,可以使用以下方法:
private static int statusBarHeight(android.content.res.Resources res) {
return (int) (24 * res.getDisplayMetrics().density);
}
可以从活动中调用:
statusBarHeight(getResources());
默认高度过去是 25dp。使用 Android Marshmallow (API 23),高度降低到 24dp。
更新:请注意,自从凹口和打孔相机时代开始以来,使用状态栏的静态高度不再有效。请改用窗口插图!
这也适用于参考链接
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
官方高度是24dp
,正如谷歌在Android 设计网页上正式声明的那样。
我有同样的问题,必须在 onCreate 中获取状态栏高度。这对我有用。
private static final int LOW_DPI_STATUS_BAR_HEIGHT = 19;
private static final int MEDIUM_DPI_STATUS_BAR_HEIGHT = 25;
private static final int HIGH_DPI_STATUS_BAR_HEIGHT = 38;
在 onCreate 内部:
DisplayMetrics displayMetrics = new DisplayMetrics();
((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(displayMetrics);
int statusBarHeight;
switch (displayMetrics.densityDpi) {
case DisplayMetrics.DENSITY_HIGH:
statusBarHeight = HIGH_DPI_STATUS_BAR_HEIGHT;
break;
case DisplayMetrics.DENSITY_MEDIUM:
statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
break;
case DisplayMetrics.DENSITY_LOW:
statusBarHeight = LOW_DPI_STATUS_BAR_HEIGHT;
break;
default:
statusBarHeight = MEDIUM_DPI_STATUS_BAR_HEIGHT;
}
看:
http://developer.android.com/reference/android/util/DisplayMetrics.html http://developer.android.com/guide/practices/ui_guidelines/icon_design.html
是的,当我尝试使用 View 时,它提供了 25px 的结果。这是整个代码:
public class SpinActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout lySpin = new LinearLayout(this);
lySpin.setOrientation(LinearLayout.VERTICAL);
lySpin.post(new Runnable()
{
public void run()
{
Rect rect = new Rect();
Window window = getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int contentViewTop =
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight = contentViewTop - statusBarHeight;
System.out.println("TitleBarHeight: " + titleBarHeight
+ ", StatusBarHeight: " + statusBarHeight);
}
}
}
}
结合了两种最佳解决方案的 Kotlin 版本
fun getStatusBarHeight(): Int {
val resourceId = resources.getIdentifier("status_bar_height", "dimen", "android")
return if (resourceId > 0) resources.getDimensionPixelSize(resourceId)
else Rect().apply { window.decorView.getWindowVisibleDisplayFrame(this) }.top
}
status_bar_height
如果存在就有价值status_bar_height
不存在,则从 Window decor 计算状态栏高度240x320 - 20 像素
320x480 - 25 像素
480x800+ - 38px
试试这个:
Rect rect = new Rect();
Window win = this.getWindow();
win.getDecorView().getWindowVisibleDisplayFrame(rect);
int statusBarHeight = rect.top;
int contentViewTop = win.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int titleBarHeight = contentViewTop - statusBarHeight;
Log.d("ID-ANDROID-CONTENT", "titleBarHeight = " + titleBarHeight );
它在活动的 onCreate 方法中对我不起作用,但是当我将它放在 onClickListener 中并给我一个 25 的测量值时它就起作用了
在 android 6.0 中状态栏的高度为 24dp
<!-- Height of the status bar -->
<dimen name="status_bar_height">24dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_height">48dp</dimen>
你可以在源代码中找到答案:frameworks\base\core\res\res\values\dimens.xml
为了解决这个问题,我使用了组合方法。这是必要的,因为在平板电脑上,系统栏在调用 display.getHeight() 时已经减去了它的像素。所以我首先检查是否存在系统栏,然后是 Ben Claytons 方法,这在手机上运行良好。
public int getStatusBarHeight() {
int statusBarHeight = 0;
if (!hasOnScreenSystemBar()) {
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
statusBarHeight = getResources().getDimensionPixelSize(resourceId);
}
}
return statusBarHeight;
}
private boolean hasOnScreenSystemBar() {
Display display = getWindowManager().getDefaultDisplay();
int rawDisplayHeight = 0;
try {
Method getRawHeight = Display.class.getMethod("getRawHeight");
rawDisplayHeight = (Integer) getRawHeight.invoke(display);
} catch (Exception ex) {
}
int UIRequestedHeight = display.getHeight();
return rawDisplayHeight - UIRequestedHeight > 0;
}
感谢@Niklas +1,这是正确的方法。
public class MyActivity extends Activity implements android.support.v4.View.OnApplyWindowInsetsListener {
Rect windowInsets;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
View rootview = findViewById(android.R.id.content);
android.support.v4.View.ViewCompat.setOnApplyWindowInsetsListener(rootview, this);
}
android.support.v4.View.WindowInsetsCompat android.support.v4.View.OnApplyWindowInsetsListener.OnApplyWindowInsets(View v, android.support.v4.View.WindowInsetsCompat insets)
{
windowInsets = new Rect();
windowInsets.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
//StatusBarHeight = insets.getSystemWindowInsetTop();
//Refresh/Adjust view accordingly
return insets;
}
}
如果代码不是 100% 正确,请原谅我是从 Xamarin C# 转换而来的,但这就是其中的原因。适用于凹槽等。
切换全屏解决方案:
此解决方案可能看起来像是一种解决方法,但它实际上说明了您的应用程序是否是全屏的(也就是隐藏状态栏):
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int barheight = size.y - findViewById(R.id.rootView).getHeight();
这样,如果您的应用当前是全屏的,barheight
则等于 0。
就我个人而言,我不得不使用它来纠正绝对 TouchEvent 坐标以解释状态栏,如下所示:
@Override
public boolean onTouch(View view,MotionEvent event) {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point(); display.getSize(size);
int YCoord = (int)event.getRawY() - size.y + rootView.getHeight());
}
无论应用程序是否全屏,这将获得绝对 y 坐标。
享受
最佳答案对某些人不起作用的原因是,在准备好渲染之前,您无法获得视图的尺寸。OnGlobalLayoutListener
实际可以使用 an来获取所述尺寸:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView();
decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= 16) {
decorView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
// Nice one, Google
decorView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
Rect rect = new Rect();
decorView.getWindowVisibleDisplayFrame(rect);
rect.top; // This is the height of the status bar
}
}
}
这是最可靠的方法。
在 Android 4.1 及更高版本上,您可以将应用程序的内容设置为显示在状态栏后面,这样内容不会随着状态栏的隐藏和显示而调整大小。为此,请使用 SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN。您可能还需要使用 SYSTEM_UI_FLAG_LAYOUT_STABLE 来帮助您的应用保持稳定的布局。
当您使用这种方法时,您有责任确保应用程序 UI 的关键部分(例如,地图应用程序中的内置控件)最终不会被系统栏覆盖。这可能会使您的应用程序无法使用。在大多数情况下,您可以通过将 android:fitsSystemWindows 属性添加到 XML 布局文件中来处理这个问题,并将其设置为 true。这会调整父 ViewGroup 的填充以为系统窗口留出空间。这对于大多数应用程序来说已经足够了。
但是,在某些情况下,您可能需要修改默认填充以获得应用所需的布局。要直接操纵您的内容相对于系统栏的布局方式(占据称为窗口“内容插入”的空间),请覆盖 fitSystemWindows(Rect insets)。当窗口的内容插入发生变化时,视图层次结构会调用 fitSystemWindows() 方法,以允许窗口相应地调整其内容。通过覆盖此方法,您可以随心所欲地处理插图(以及因此您的应用程序的布局)。
表格: https ://developer.android.com/training/system-ui/status.html#behind
如果您确切知道尺寸 VS 高度
像
例如,在屏幕尺寸为 320 X 480 的设备中,状态栏高度为 25px,对于 480 x 800 的设备,状态栏高度必须为 38px
然后你可以得到你的视图的宽度/屏幕大小你可以使用 if else 语句来获取状态栏的高度
由于现在可以使用多窗口模式,因此您的应用顶部可能没有状态栏。
以下解决方案会自动为您处理所有案例。
android:fitsSystemWindows="true"
或以编程方式
findViewById(R.id.your_root_view).setFitsSystemWindows(true);
您还可以通过以下方式获得根视图
findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)
有关获取根视图的更多详细信息,请参阅 - https://stackoverflow.com/a/4488149/9640177
由于我的 Pixel 3XL 中的缺口,这个问题最近与我相关。我真的很喜欢android 开发者的解决方案,但我希望能够随意获取状态栏高度,因为它对于我需要播放的全屏动画来说是特别必要的。下面的函数启用了可靠的查询:
private val DEFAULT_INSET = 96
fun getInsets(view: View?): Int {
var inset = DEFAULT_INSET
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {//Safe because only P supports notches
inset = view?.rootWindowInsets?.stableInsetTop ?: DEFAULT_INSET
}
return inset
}
fun blurView(rootView: View?, a: SpacesActivity?) {
val screenBitmap = getBitmapFromView(rootView!!)
val heightDifference = getInsets(rootView)
val croppedMap = Bitmap.createBitmap(
screenBitmap, 0, heightDifference,
screenBitmap.width,
screenBitmap.height - heightDifference)
val blurredScreen = blurBitmap(croppedMap)
if (blurredScreen != null) {
val myDrawable = BitmapDrawable(a!!.resources, blurredScreen)
a.errorHudFrameLayout?.background = myDrawable
a.appBarLayout?.visibility = View.INVISIBLE
}
}
然后在活动课上:
fun blurView() {
this.runOnUiThread {
Helper.blurView(this)
}
}
您当然希望将活动的弱引用传递给静态 Helper 类方法参数,但为了简洁起见,我在此示例中避免使用。blurBitmap
和出于同样的errorHudFrameLayout
原因被省略,因为它们与获取状态栏的高度没有直接关系。