Android 状态栏的高度?
有没有办法获得状态栏+标题栏的高度?查看dev论坛显示了相同的问题,但没有解决方案(我可以找到) 我知道我们可以在初始布局通过后获得它,但我希望在活动的onCreate()中获得它 谢谢 获取活动的Android 状态栏的高度?,android,Android,有没有办法获得状态栏+标题栏的高度?查看dev论坛显示了相同的问题,但没有解决方案(我可以找到) 我知道我们可以在初始布局通过后获得它,但我希望在活动的onCreate()中获得它 谢谢 获取活动的onCreate()方法上状态栏的高度,请使用以下方法: public int getStatusBarHeight() { int result = 0; int resourceId = getResources().getIdentifier("status_bar_h
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;
}
将runnable附加到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,并添加毫秒值作为第二个参数 我认为更好的计算方法是计算全屏的高度减去主布局
phoneBarsHeight = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight()
- mainView.getHeight();
您可以将其放入onGlobalLayout()
。这也适用于平板电脑,我在Theme.NoTitleBar上试用过,但它必须始终有效
也许您甚至可以通过将
mainView.getHeight()
更改为mainView.getmeasuredeheight()
来增强它并使用它onCreate()
,我建议下一个代码:
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
品牌:三星,
设备:马古罗,
董事会:金枪鱼,
cpu_abi:armeabi-v7a,
显示:ICL53F.M420KREL08,
制造商:三星,
型号:Galaxy Nexus,
版本:4.0.2,
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;
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;
设备1的标题栏位于屏幕顶部,状态栏的软件按钮位于屏幕底部
2) 装置2
装置:好极了,
董事会:太好了,
cpu_abi:armeabi-v7a,
显示器:FRG83G,
制造商:HTC,
型号:HTC Desire,
版本发布:2.2.2,
sdk版本:8
屏幕分辨率:800 x 400。这个设备有硬件按钮
结果:
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;
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)
(这对于设备2不正确-它给出的是0而不是38)
变体:
display.getHeight() - v.getBottom() + rect.top
在这两种情况下都给出了正确的结果
更新
3) 另一个示例(第三个设备):
品牌:LGE,
设备:v909,
cpu_abi:armeabi-v7a,
显示器:HMJ37,
型号:LG-V909,
版本:3.1,
版本: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()中答案不起作用。
:
我在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;
}
我希望这对任何遇到这个问题的人都有帮助。Jorgesys发布的解决方案非常好,但它在onCreate()方法中不起作用。 我想这是因为状态栏和标题栏是在onCreate()之后创建的 解决方案很简单-您应该将代码放在runnable中,并在onCreate()之后使用
root.post((runnable操作))执行它代码>
因此,整个解决方案:
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);
}
});
对于像我这样希望在XML布局中使用它的人,我发现它:
<...
android:layout_marginTop="@*android:dimen/status_bar_height"
... />
不要被Android Studio(2.2预览版3——在撰写本文时)不支持这个概念所迷惑。运行时会这样做。我是从谷歌的源代码中获取的。从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()
中,但您可以为窗口附加添加一个侦听器并在那里执行此操作-在这里,我将状态栏inset添加到我的工具栏的大小,我将隐藏并显示它,以及状态栏。显示时,我希望状态栏位于其顶部,因此我将状态栏高度添加到工具栏的顶部填充中
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) {
}
});
获取状态栏高度的支持方式是使用从API 21+开始的类:
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 talk-成为主窗口装配工(幻灯片可用)。这可能看起来不相关,但大多数情况下,人们寻找状态栏高度的原因是为了偏移自己的视图,以便不将其放置在状态栏下
通过在视图上设置fitsystemwindows
,您希望“按下”状态栏以给状态栏留出空间,它将根据每个设备上状态栏的大小自动完成。填充将添加到将此属性设置为true
的视图中
请记住,填充只会添加到层次结构中的第一个视图中,fitSystemWindows
设置为true
例如,这适用于状态栏为半透明的情况。确保为未设置fitSystemWindows
的活动设置主题,否则填充将添加到活动中(因为它是hie中的第一个)
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);
}
});
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
}
}
}