我正在实现一个自助模式应用程序,并成功地使应用程序在Android 4.3之后全屏且没有状态栏出现,但无法在4.3和4.4版本中隐藏状态栏,因为当我们在屏幕顶部向下滑动时状态栏会出现。
我尝试以下方法使其全屏:
- 在清单文件中指定全屏主题
- 设置窗口标志,即setFlags
- setSystemUiVisibility
可能是重复的问题,但没有找到具体的解决方案。
最终我想要的是如何在一个活动中永久隐藏状态栏?在Android 4.3、4.4、5和6版本中均适用。
我正在实现一个自助模式应用程序,并成功地使应用程序在Android 4.3之后全屏且没有状态栏出现,但无法在4.3和4.4版本中隐藏状态栏,因为当我们在屏幕顶部向下滑动时状态栏会出现。
我尝试以下方法使其全屏:
可能是重复的问题,但没有找到具体的解决方案。
最终我想要的是如何在一个活动中永久隐藏状态栏?在Android 4.3、4.4、5和6版本中均适用。
由于无法在KitKat设备上防止状态栏出现在全屏模式中,因此我们进行了一项修改以满足要求,即阻止状态栏扩展。
为了使此方法起作用,该应用程序未被制成全屏。我们在状态栏上叠加了一个覆盖层并消耗了所有输入事件,从而防止了状态栏的扩展。
注意:
更新:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
代码:
WindowManager manager = ((WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to recieve touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (50 * getResources()
.getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
customViewGroup view = new customViewGroup(this);
manager.addView(view, localLayoutParams);
在Android M中,您需要获取额外的权限才能制作覆盖层。 android.permission.SYSTEM_ALERT_WINDOW
是不够的!因此,我使用了Abhimaan答案中的代码在 disableStatusBar()
中,并且必须创建意图以打开正确的设置对话框。我还在 onDestroy()
中添加了删除视图,以便在应用程序退出时启用状态栏。我还将叠加高度减小到40,因为它似乎足够了。该代码适用于5.1和6.0。
public static final int OVERLAY_PERMISSION_REQ_CODE = 4545;
protected CustomViewGroup blockingView = null;
@Override
protected void onDestroy() {
super.onDestroy();
if (blockingView!=null) {
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
manager.removeView(blockingView);
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Toast.makeText(this, "Please give my app this permission!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
} else {
disableStatusBar();
}
}
else {
disableStatusBar();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (!Settings.canDrawOverlays(this)) {
Toast.makeText(this, "User can access system settings without this permission!", Toast.LENGTH_SHORT).show();
}
else
{ disableStatusBar();
}
}
}
protected void disableStatusBar() {
WindowManager manager = ((WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
localLayoutParams.height = (int) (40 * getResources().getDisplayMetrics().scaledDensity);
localLayoutParams.format = PixelFormat.TRANSPARENT;
blockingView = new CustomViewGroup(this);
manager.addView(blockingView, localLayoutParams);
}
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
即可。 - Alexey Ozerov现在已经过了一段时间,我不记得所有的细节,但CustomViewGroup是覆盖主ViewGroup的类,可以检测用户从顶部向下滑动以显示状态栏。但我们不想显示它,因此检测到用户的拦截并忽略任何进一步的操作,即Android OS将不会收到打开隐藏状态栏的信号。
然后还包括用于显示和隐藏状态栏的方法,您可以将其原样复制/粘贴到您希望显示/隐藏状态栏的代码中。
/**
* This class creates the overlay on the status bar which stops it from expanding.
*/
public static class CustomViewGroup extends ViewGroup {
public CustomViewGroup(Context context) {
super(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.v("customViewGroup", "********** Status bar swipe intercepted");
return true;
}
}
public static void allowStatusBarExpansion(Context context) {
CustomViewGroup view = new CustomViewGroup(context);
WindowManager manager = ((WindowManager) context.getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
manager.removeView(view);
}
// Stop expansion of the status bar on swipe down.
public static void preventStatusBarExpansion(Context context) {
WindowManager manager = ((WindowManager) context.getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE));
Activity activity = (Activity) context;
WindowManager.LayoutParams localLayoutParams = new WindowManager.LayoutParams();
localLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
localLayoutParams.gravity = Gravity.TOP;
localLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
// this is to enable the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
localLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
//https://dev59.com/hnNA5IYBdhLWcg3wUL5Y
int resId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android");
int result = 0;
if (resId > 0) {
result = activity.getResources().getDimensionPixelSize(resId);
}
localLayoutParams.height = result;
localLayoutParams.format = PixelFormat.TRANSPARENT;
CustomViewGroup view = new CustomViewGroup(context);
manager.addView(view, localLayoutParams);
}
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@acbb68b -- permission denied for window type 2010
。 我该如何解决它? - Cursed