有没有一种方法可以获取状态栏和标题栏的高度?检查开发人员论坛会显示相同的问题,但没有解决方案(我可以找到)。
我知道我们可以在初始布局通过后获得它,但是我希望在我的活动的onCreate()中获得它。
谢谢
有没有一种方法可以获取状态栏和标题栏的高度?检查开发人员论坛会显示相同的问题,但没有解决方案(我可以找到)。
我知道我们可以在初始布局通过后获得它,但是我希望在我的活动的onCreate()中获得它。
谢谢
Answers:
Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int StatusBarHeight= rectgle.top;
int contentViewTop=
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int TitleBarHeight= contentViewTop - StatusBarHeight;
Log.i("*** Jorgesys :: ", "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;
}
"?attr/actionBarSize"
对于那些像我一样,想要在您的XML布局中使用它的人:
<...
android:layout_marginTop="@*android:dimen/status_bar_height"
... />
不要被Android Studio(2.2预览版3 –在撰写本文时)不支持此概念所迷惑。运行时可以。我从Google的源代码中获取了它。
You must supply a layout_height(width) attribute如果在布局文件上使用它会给您错误。
尽管这是一个老问题,但我发现答案不适用于onCreate():
我从这里找到了在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,因此该功能对我很有用!
获取状态栏高度的支持方法是使用WindowInsets从API 21+开始的类:
customView.setOnApplyWindowInsetsListener((view, insets) -> {
// Handle insets
return insets.consumeSystemWindowInsets();
});
或WindowInsetsCompat用于支持库:
ViewCompat.setOnApplyWindowInsetsListener(customView, (view, insets) -> {
// Handle insets
return insets.consumeSystemWindowInsets();
});
您还可以onApplyWindowInsets在视图内覆盖方法:
public class CustomView extends View {
@Override
public WindowInsets onApplyWindowInsets(final WindowInsets insets) {
final int statusBarHeight = insets.getStableInsetTop();
return insets.consumeStableInsets();
}
}
有关更多详细信息,我建议检查Chris Banes谈话-成为主窗口装配工(此处提供幻灯片)。
我建议下一个代码:
Rect rect = new Rect();
Window window = activity.getWindow();
if (window != null) {
window.getDecorView().getWindowVisibleDisplayFrame(rect);
android.view.View v = window.findViewById(Window.ID_ANDROID_CONTENT);
android.view.Display display = ((android.view.WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
//return result title bar height
return display.getHeight() - v.getBottom() + rect.top;
}
两个例子:
1)设备1品牌:三星,设备:maguro,面板:金枪鱼,cpu_abi:armeabi-v7a,显示屏:ICL53F.M420KREL08,制造商:三星,型号:Galaxy Nexus,版本:4.0.2,版本SD:14 ;
屏幕分辨率:1280 x720。此设备上没有硬件按钮。
结果:
rect: left=0 right=720 top=72 bottom=1208;
v: left=0 right=720 top=72 bottom=1208;
display: height=1208 width=720;
correct result=72;
设备1在屏幕顶部具有标题栏,在屏幕底部具有状态栏和软件按钮。
2)设备2设备:bravo,板卡:bravo,cpu_abi:armeabi-v7a,显示屏:FRG83G,制造商:HTC,型号:HTC Desire,ver.release:2.2.2,ver.sdk:8,
屏幕分辨率:800 x400。此设备具有硬件按钮。
结果:
rect: left=0 right=480 top=38 bottom=800;
v: left=0 right=480 top=0 bottom=800;
display: height=800 width=480;
correct result: phone_bar_height=38;
设备2在屏幕顶部具有标题栏,而根本没有状态栏。
上面提出了两种解决方案:
A) v.getTop() - rect.top
(这对于设备1是不正确的-它给出0而不是72)
B) display.getHeight() - v.getHeight()
(对于设备2不正确-它给出的是0而不是38)
变体:
display.getHeight() - v.getBottom() + rect.top
在两种情况下都能给出正确的结果。
更新资料
3)再举一个例子(第三个设备):品牌:LGE,设备:v909,cpu_abi:armeabi-v7a,显示:HMJ37,型号:LG-V909,版本发行:3.1,版本SDK:12
rect: left=0 right=1280 top=0 bottom=720
v: left=0 right=1280 top=0 bottom=720
Display: height=768 width=1280
phone_bar_height=48
设备3具有水平方向,在屏幕顶部没有标题栏,而在屏幕底部具有状态栏。
所以在这里:
int size_of_title_bar = rect.top;
int size_of_status_bar = display.getHeight() - v.getBottom();
对设备2和3正确。我不确定设备1。用户向我发送了设备1的屏幕截图。那里有一个带有软件按钮的状态栏。但是表达式“ display.getHeight()-v.getBottom()”给出0。
您也可以使用此博客文章的方式,确定在android的dimens.xml文件中找到的状态栏的尺寸。描述。
这可以获取状态栏的高度,而无需等待绘图。
引用博客文章中的代码:
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
您需要将此方法放在ContextWrapper类中。
在您的onCreate方法中将一个可运行对象附加到您的一个视图中,然后将上面的代码放在其中。当它们连接到屏幕时,这将导致应用程序计算状态栏+标题屏幕的高度。
看一下下面的代码:
myView.post(new Runnable() {
@Override
public void run() {
Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int StatusBarHeight= rectgle.top;
int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int TitleBarHeight= contentViewTop - StatusBarHeight;
}
});
如果仍然不能解决问题,请尝试调用视图的postDelayed方法而不是post并添加毫秒值作为第二个参数。
view您致电后()上是任意的是否正确?不管view您使用哪种方法Runnable将它们放入相同的UI线程消息队列中?我知道它可以工作,但是有没有解释过posted可运行/消息仅在views被测量并完成layout()之后才运行的地方?
我认为更好的计算方法是获得全屏高度减去我们的主布局
phoneBarsHeight = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight()
- mainView.getHeight();
你可以把它放进去 onGlobalLayout()。这也适用于平板电脑,我在Theme.NoTitleBar上尝试过,但必须始终有效。
也许您甚至可以onCreate()通过更改mainView.getHeight()为来增强和使用它mainView.getMeasuredHeight()。
Jorgesys发布的解决方案非常好,但是在onCreate()方法中不起作用。我猜这是因为statusbar和titlebar是在onCreate()之后创建的。
解决方案很简单-您应该将代码放入可运行的内部,并通过使用onCreate()之后执行它 root.post((Runnable action) );
所以整个解决方案:
root = (ViewGroup)findViewById(R.id.root);
root.post(new Runnable() {
public void run(){
Rect rectgle= new Rect();
Window window= getWindow();
window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
int StatusBarHeight= rectgle.top;
int contentViewTop=
window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
int TitleBarHeight= contentViewTop - StatusBarHeight;
Log.i("*** jakkubu :: ", "StatusBar Height= " + StatusBarHeight +
" , TitleBar Height = " + TitleBarHeight);
}
});
我在这里找到
从API 23开始,有一种更好的解决方案来获取状态栏的高度。API 23添加了一项WindowInsets功能,因此您可以使用此代码获取系统插图的大小,在本例中为顶部。
public int getStatusBarHeight() {
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
return binding.mainContent.getRootWindowInsets().getStableInsetTop();
}
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if(resourceId != 0) {
return getResources().getDimensionPixelSize(resourceId);
}
return 0;
}
请注意,getRootWindowInsets()在将视图附加到窗口之后,它将返回null,因此不能直接在其中使用它,onCreate()但是您可以为窗口附加添加侦听器,然后在此处执行此操作-在这里,我将状态栏插入添加到大小隐藏和显示的工具栏以及状态栏。当它显示时,我希望状态栏位于其顶部,因此我将状态栏的高度添加到工具栏的顶部填充中。
binding.mainContent.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
binding.toolbar.setPadding(binding.toolbar.getPaddingLeft(),
binding.toolbar.getPaddingTop() + getStatusBarHeight(),
binding.toolbar.getPaddingRight(), binding.toolbar.getPaddingBottom());
binding.mainContent.removeOnAttachStateChangeListener(this);
}
@Override
public void onViewDetachedFromWindow(View view) {
}
});
好。最终答案!!!一种没有副作用,依赖于记录的行为,支持Q,保险开关,根据方向&c具有不同状态栏大小的设备的设备。
protected void onCreate(Bundle savedInstanceState) {
...
setContentView(R.layout.activity_main);
....
// Use The topmost view of the activity, which
// is guaranteed to be asked about window insets/
View rootView = findViewById(R.id.root_view_of_your_activity);
ViewCompat.setOnApplyWindowInsetsListener(rootView, new OnApplyWindowInsetsListener() {
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets)
{
//THIS is the value you want.
statusBarHeight = insets.getSystemWindowInsetTop();
// Let the view handle insets as it likes.
return ViewCompat.onApplyWindowInsets(v,insets);
}
});
回调发生在onStart()之后,第一次布局之前,并且此后偶尔发生。
这看起来似乎无关紧要,但在大多数情况下,人们寻找状态栏高度的原因是要抵消自己的视图,以使他们不会被置于其下方。
通过fitsSystemWindows在视图上进行设置,您可以“按下”以在状态栏上留出空间,这将根据每个设备上状态栏的大小自动完成。填充将添加到该属性设置为的视图中true。
请记住,填充将仅添加到层次结构中的第一个视图中,fitSystemWindows设置为true
例如,这适用于状态栏为半透明的情况。确保您将主题设置为没有的活动fitSystemWindows设置,否则填充将被添加到活动中(因为它是层次结构中的第一个)。
本文是该主题的不错的阅读