喔…这标题,吓我一跳;
请稍等…
思绪整理中…
Android中, 经常被这些高度绊脚. 完全进入懵逼的状态, 有木有?
请允许我,介绍清楚!
通常情况下, 宽度都是很友好的,但是高度就呵呵, 所以本文只介绍高度的计算.
2018-10-17更新
安卓开发过程中, 经常被状态栏的高度
导航栏的高度
键盘的高度
搞的稀里糊涂. 经过一段时间整理, 似乎找到了比以前更有效的方法,如下:
所有操作只针对Activity
(dialog 不行)
的window
,因为Android
界面的载体都是window
对象:
可视区域
final View decorView = window.getDecorView();
Rect outRect = new Rect();
decorView.getWindowVisibleDisplayFrame(outRect);
//可视区域
outRect.top -> 可视区域顶部的坐标 (也就是状态栏的高度)
outRect.bottom -> 可视区域底部的坐标 (屏幕高度-导航栏-键盘的高度)
public class DecorUtil {
/**
* 请勿在dialog中使用
* <p>
* 主题的 android:windowTranslucentStatus 属性, 会影响 contentView 的 padding top.
* <p>
* 如果设置了 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN , 那么 contentView 的 padding top 都是 0
*/
public static void demo(@NonNull final Window window) {
final View decorView = window.getDecorView();
int measuredHeight = decorView.getMeasuredHeight();
if (measuredHeight <= 0) {
decorView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
decorView.getViewTreeObserver().removeOnPreDrawListener(this);
demo(window);
return true;
}
});
} else {
Rect outRect = new Rect();
decorView.getWindowVisibleDisplayFrame(outRect);
L.w("可视区域:" + outRect);
L.w("屏幕高度:" + measuredHeight);
if (decorView instanceof ViewGroup) {
int childCount = ((ViewGroup) decorView).getChildCount();
if (childCount > 0) {
View contentView = ((ViewGroup) decorView).getChildAt(0);
L.w("内容高度:" + contentView.getMeasuredHeight() + " p:" + contentView.getPaddingTop());
}
if (childCount > 1) {
View childView = ((ViewGroup) decorView).getChildAt(1);
if (isStatusBar(decorView, childView)) {
L.w("状态栏高度:" + childView.getMeasuredHeight());
} else if (isNavigationBar(decorView, childView)) {
L.w("导航栏高度:" + childView.getMeasuredHeight());
} else {
L.w("未知:" + childView);
}
}
if (childCount > 2) {
View childView = ((ViewGroup) decorView).getChildAt(2);
if (isStatusBar(decorView, childView)) {
L.w("状态栏高度:" + childView.getMeasuredHeight());
} else if (isNavigationBar(decorView, childView)) {
L.w("导航栏高度:" + childView.getMeasuredHeight());
} else {
L.w("未知:" + childView);
}
}
}
}
}
private static boolean isStatusBar(@NonNull View decorView, @NonNull View childView) {
if (childView.getTop() == 0 &&
childView.getMeasuredWidth() == decorView.getMeasuredWidth() &&
childView.getBottom() < decorView.getBottom()
) {
return true;
}
return false;
}
private static boolean isNavigationBar(@NonNull View decorView, @NonNull View childView) {
if (childView.getTop() > decorView.getTop() &&
childView.getMeasuredWidth() == decorView.getMeasuredWidth() &&
childView.getBottom() == decorView.getBottom()
) {
return true;
}
return false;
}
}
通过以上方法, 可以获得:状态栏高度
导航栏高度以及是否显示
键盘的高度以及是否显示
已下是旧文
1:DecorView的高度
DecorView的高度代表的是: 整个装饰窗口的高度, 这个高度包括:状态烂的高度和导航栏的高度.(状态栏和导航栏通常叫做装饰窗口, 而ActionBar不属于装饰窗口)
这个高度, 可以代表着整个玻璃屏幕的高度.
获取方式:mActivity.getWindow().getDecorView()
2.Window的RootView的高度
RootView的获取方式:mActivity.getWindow().findViewById(Window.ID_ANDROID_CONTENT);
这个View对应的高度, 可以表示当前应用程序的有效高度.
在没有任何修饰的情况下, 应用程序的高度是去掉状态栏和导航栏后的高度;
也就是 (DecorView的高度)-(状态栏的高度)-(导航栏的高度);
但是,如果你使用:
setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
这个方法, 那么RootView的高度会和DecorView的高度相等;
3:heightPixels的高度
heightPixels 这个高度表示…屏幕有效的高度;;;
什么意思呢?
就是:DecorView的高度去掉导航栏的高度.
这个高度不管你有没有隐藏导航栏, 这个值都不会改变;
获取方式:mActivity.getResources().getDisplayMetrics().heightPixels
所以:
番外:如果你想知道你的手机有没有导航栏:
如果 (DecorView的高度)-(heightPixels) > 0 说明 你的手机有导航栏
番外:如果你想知道你的程序有没有隐藏导航栏:
情况1:设置了SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN属性:
如果 (RootView的高度)-(heightPixels) > 0 说明 显示了导航栏
情况2:没有设置SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN属性:
如果 (RootView的高度+状态栏的高度)-(heightPixels) > 0 说明 显示了导航栏
附加1 获取状态栏的高度
正常情况下: (heightPixels) - (RootView的高度) = 状态栏的高度
但是如果你设置了View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN或者View.SYSTEM_UI_FLAG_HIDE_NAVIGATION属性的话,这种方法就不准确了.
万能,100%准确的方法:
getResources().getDimensionPixelSize(getResources().getIdentifier(“status_bar_height”, “dimen”, “android”));
附加2:获取导航栏的高度
正常情况下: (DecorView的高度) - (heightPixels) = 导航栏的高度
但是如果你设置了View.SYSTEM_UI_FLAG_HIDE_NAVIGATION属性的话,这种方法就不准确了.
万能,100%准确的方法:
getResources().getDimensionPixelSize(getResources().getIdentifier(“navigation_bar_height”, “dimen”, “android”));