Android中状态栏的高度是多少?总是一样吗?
从我的测量来看,它似乎是25dp,但是我不确定在所有平台上它是否具有相同的高度。
(我想知道这可以正确地实现从没有状态栏的活动到具有状态栏的活动的渐变过渡)
Android中状态栏的高度是多少?总是一样吗?
从我的测量来看,它似乎是25dp,但是我不确定在所有平台上它是否具有相同的高度。
(我想知道这可以正确地实现从没有状态栏的活动到具有状态栏的活动的渐变过渡)
Answers:
更新 ::
好的,状态栏的高度取决于屏幕尺寸,例如,在屏幕尺寸为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;
}
window.getDecorView().getWindowVisibleDisplayFrame(rectangle)
如果您处于多窗口模式+纵向旋转+第二窗口,则不是获取状态栏高度的正确方法。您将获得巨大的价值(包括第一高度)。
在我用来获取状态栏高度的所有代码示例中,实际上唯一可以使用的onCreate
方法工作的示例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/中找到
在MDPI设备上,状态栏为25px。我们可以将其用作基础并乘以密度(向上舍入)以获取任何设备上状态栏的高度:
int statusBarHeight = Math.ceil(25 * context.getResources().getDisplayMetrics().density);
供参考:ldpi = .75,mdpi = 1,hdpi = 1.5,xhdpi = 2
硬编码大小或使用反射来获取的值status_bar_height
被认为是不好的做法。克里斯· 贝恩斯( Chris Banes)在纽约Droidcon大会上谈到了这一点。推荐的获取状态栏大小的方法是通过OnApplyWindowInsetsListener:
myView.setOnApplyWindowInsetsListener { view, insets -> {
val statusBarSize = insets.systemWindowInsetTop
return insets
}
这是在API 20中添加的,也可以通过ViewAppCompat向后移植。
我将一些解决方案合并在一起:
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
根据Google设计指南;状态栏的高度为24 dp。
如果要获取状态栏的高度(以像素为单位),可以使用以下方法:
private static int statusBarHeight(android.content.res.Resources res) {
return (int) (24 * res.getDisplayMetrics().density);
}
可以通过以下方式从活动中调用:
statusBarHeight(getResources());
这也适用于Refreence 链接
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中获取状态栏的高度。这对我有用。
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
24dp
如Google在Android Design网页上所述,官方高度为。
是的,当我尝试使用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);
}
}
}
}
尝试这个:
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 \ res \ values \ dimens.xml
@android:dimen/status_bar_height
不适用于我
为了解决这个问题,我使用了一种组合方法。这是必要的,因为在平板电脑上,调用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坐标。
请享用
在Android 4.1及更高版本上,您可以将应用程序的内容设置为显示在状态栏的后面,以使内容不会随着状态栏的隐藏和显示而调整大小。为此,请使用SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN。您可能还需要使用SYSTEM_UI_FLAG_LAYOUT_STABLE来帮助您的应用维持稳定的布局。
使用这种方法时,您有责任确保应用程序UI的关键部分(例如,Maps应用程序中的内置控件)最终不会被系统栏覆盖。这可能会使您的应用无法使用。在大多数情况下,您可以通过将android:fitsSystemWindows属性添加到XML布局文件(设置为true)来处理此问题。这将调整父ViewGroup的填充以为系统窗口留出空间。这对于大多数应用程序来说已经足够了。
但是,在某些情况下,您可能需要修改默认填充以获取所需的应用布局。要直接操纵内容相对于系统栏的布局方式(系统栏占据着一个窗口的“内容插入物”空间),请覆盖fitSystemWindows(Rect插入物)。当窗口的内容插入更改时,视图层次结构将调用fitSystemWindows()方法,以允许窗口相应地调整其内容。通过覆盖此方法,您可以根据需要处理插图(以及应用程序的布局)。
形式:https: //developer.android.com/training/system-ui/status.html#behind
如果您确切知道尺寸VS高度
喜欢
例如,在屏幕尺寸为320 X 480的设备中,状态栏高度为25px,对于屏幕尺寸为480 x 800的设备,状态栏高度必须为38px
那么您就可以获取视图的宽度/屏幕大小,只需使用if else语句即可获取状态栏的高度
最佳答案对某些人不起作用的原因是,在准备好渲染视图之前,您无法获得视图的尺寸。OnGlobalLayoutListener
实际上可以使用来获得上述尺寸:
@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:fitsSystemWindows="true"
或以编程方式
findViewById(R.id.your_root_view).setFitsSystemWindows(true);
您还可以通过以下方式获得根视图
findViewById(android.R.id.content).getRootView();
or
getWindow().getDecorView().findViewById(android.R.id.content)
有关获取root-view的更多详细信息,请参阅-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
被省略,同样的原因,因为它们不直接涉及到获得状态栏的高度。
结合两个最佳解决方案的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
不存在,则根据“窗口装饰”计算状态栏的高度