繁体   English   中英

Android中状态栏的高度[重复]

[英]Height of status bar in Android [duplicate]

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

(旧方法)要在您的 Activity 的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;
} 

在我用来获取状态栏高度的所有代码示例中,唯一似乎在ActivityonCreate方法中有效的代码示例是:

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 Design 网页上官方声明的那样。

我有同样的问题,必须在 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);
            }
        }
    }
}

240x320 - 20 像素

320x480 - 25 像素

480x800+ - 38 像素

尝试这个:

    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 的测量值时起作用

结合两个最佳解决方案的 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
}
  1. 如果存在则采用status_bar_height
  2. 如果status_bar_height不存在,则根据 Window 装饰计算状态栏高度

状态栏的高度在 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获取所述尺寸:

@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 类方法参数,但为了简洁起见,我在本示例中没有提及。 出于同样的原因,省略了blurBitmaperrorHudFrameLayout ,因为它们与获取状态栏的高度没有直接关系。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM