有没有办法获得状态栏+标题栏的高度?检查开发论坛显示相同的问题,但没有解决方案(我能找到)。
我知道我们可以在初始布局传递之后得到它,但我希望在我的活动的onCreate()中得到它。
由于
答案 0 :(得分:93)
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;
}
答案 1 :(得分:39)
虽然这是一个老问题,但我发现答案在onCreate()
中无效:
我发现here中的代码在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;
}
我希望这对遇到这个问题的任何人都有帮助。
答案 2 :(得分:34)
对于像我这样想要在XML布局中使用它的人:
repositories {
maven {
url "https://jitpack.io"
}
}
不要被Android工作室弄糊涂(2.2预览3 - 在写作的那一刻)并不支持这个概念。运行时有。我是从Google的源代码中获取的。
答案 3 :(得分:7)
获取状态栏高度的支持方法是从API 21 +开始使用WindowInsets
类:
customView.setOnApplyWindowInsetsListener((view, insets) -> {
// Handle insets
return insets.consumeSystemWindowInsets();
});
支持库的
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的演讲 - 成为主窗口钳工(可用幻灯片here)。
答案 4 :(得分:6)
我建议下一个代码:
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, ver.release:4.0.2, ver.sdk:14;
屏幕分辨率:1280 x 720.此设备上没有硬件按钮。
结果:
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 x 400.此设备有硬件按钮。
结果:
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, ver.release:3.1, ver.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.
答案 5 :(得分:6)
您还可以使用this blog post描述的方式获取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类中。
答案 6 :(得分:5)
将onnable附加到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,并添加毫秒值作为第二个参数。
答案 7 :(得分:2)
我认为更好的计算方法是获得全屏高度减去我们的主要布局
phoneBarsHeight = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight()
- mainView.getHeight();
你可以把它放在onGlobalLayout()
中。这也适用于平板电脑,我在Theme.NoTitleBar上尝试过它,但它必须始终有效。
也许您甚至可以通过将onCreate()
更改为mainView.getHeight()
来增强并使用mainView.getMeasuredHeight()
。
答案 8 :(得分:1)
Jorgesys发布的解决方案非常好,但它在onCreate()方法中不起作用。 我想这是因为在onCreate()之后创建了状态栏和标题栏。
解决方案很简单 - 您应该将代码置于runnable中并使用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);
}
});
我发现它here
答案 9 :(得分:1)
从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) {
}
});
答案 10 :(得分:1)
好的。最终答案!!!一种没有副作用,依赖于记录的行为,支持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()之后,第一个布局之前,偶尔在此之后。
答案 11 :(得分:0)
这似乎无关紧要,但在大多数情况下,人们寻找状态栏高度的原因是要偏移自己的视图,以便不将其置于其下方。
通过在要“下推”的视图上设置fitsSystemWindows
,以在状态栏上留出空间,将根据每个设备上状态栏的大小自动完成此操作。填充将添加到该属性设置为true
的视图中。
请记住,填充只会在fitSystemWindows
设置为true
的层次结构中添加到第一个视图中
例如,这适用于状态栏为半透明的情况。确保将主题设置为未设置fitSystemWindows
的活动,否则填充将被添加到活动中(因为它是层次结构中的第一个)。
This article是有关该主题的好书
答案 12 :(得分:0)
针对 API 30,我已成功使用更新的 Nicklas 答案(参考:https://stackoverflow.com/a/47125610/2163045)
在我的示例中,我在全屏 WindowCompat.setDecorFitsSystemWindows(window, false)
Activity 中动态调整自定义工具栏高度
在 GooglePixel 5 上测试
class MyActivity : ViewBindingActivity<LayoutBinding>() {
...
override fun created(binding: LayoutBinding, savedInstanceState: Bundle?) {
binding.root.setOnApplyWindowInsetsListener { _, insets ->
val statusBarHeight = insets.getInsets(WindowInsets.Type.statusBars()).top // <- HERE YOU ARE
val toolbarHeight = getDimenPx(R.dimen.toolbar_height)
binding.toolbar.layoutParams.height = statusBarHeight + toolbarHeight
insets
}
}
}