【问题标题】:Prevent status bar for appearing android (modified)防止状态栏出现android(修改)
【发布时间】:2014-10-06 16:46:36
【问题描述】:

我正在实现一个自助服务终端模式应用程序,并且我已经成功地使应用程序在 4.3 后没有状态栏出现全屏,但无法在 4.3 和 4.4 中隐藏状态栏,因为当我们在顶部向下滑动时出现状态栏屏幕。

我试着让它全屏

  • 在清单中指定全屏主题
  • 设置窗口标志即setFlags
  • setSystemUiVisibility

可能重复但未找到具体解决方案

Permanently hide Android Status Bar

最后我想要的是,如何在活动中永久隐藏状态栏?在 android 4.3,4.4,5,6 版本中

【问题讨论】:

    标签: android statusbar kiosk


    【解决方案1】:

    我们无法阻止在 kitkat 设备中以全屏模式显示状态,所以做了一个仍然符合要求的 hack,即阻止状态栏扩展。

    为此,该应用并未全屏显示。我们在状态栏上放置了一个覆盖层并消耗了所有输入事件。它阻止了状态扩展。

    注意:

    • customViewGroup 是自定义类,它扩展了任何 布局(框架,相对布局等)并消耗触摸事件。
    • 消费触摸事件覆盖onInterceptTouchEvent方法 视图组并返回 true

    更新

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> 
    

    customViewGroup implementation

    代码:

    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);
    

    【讨论】:

    • 经过 2 周的尝试,绝对是唯一对我有用的东西。完全阻止状态栏扩展
    • @user1416682 这是一个非常基本的 customViewGroup,可以帮助您入门。 link
    • @AbhimaanMadhav,我没想到 :) 调用 manager.removeView(view) 对我来说就足够了。顺便说一句,你可以应用它来禁用软按钮吗?目前它对我不起作用。
    • 不再适用于 Android 8.0 或 Oreo 设备。
    • @Abhimaan 在 oreo+ 设备上,任何用户添加的窗口或视图都不能显示在状态栏上方,状态栏始终可以下拉。
    【解决方案2】:

    在 Android M 中,您必须获得额外的权限才能制作叠加层。 android.permission.SYSTEM_ALERT_WINDOW 还不够!因此,我使用了 disableStatusBar() 中 Abhimaan 的答案中的代码,并且必须有意打开正确的设置对话框。我还在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);
    }
    

    【讨论】:

    • (int) (40 * getResources() 使用 40 的决策标准是什么?
    • 我相信状态栏通常在 40 dp 左右
    • 不幸的是,没有一个解决方案对我有用,包括这个。在我的 Kiosk 应用程序中,我仍然可以下拉状态栏。我的应用程序处于固定模式,这意味着状态栏是空白的,但无​​论如何,我都可以从顶部滑动它。我不明白这是什么类型的固定,为什么Android不会在固定模式下永久隐藏它,无论如何它都是空白的。
    • 它在奥利奥中不起作用请也支持奥利奥
    • @Honza:对于 Android 4.4 和 5,将权限放在 Manifest 文件中就足够了 &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&gt;
    【解决方案3】:

    对于我从事的一个项目,我找到了解决方案,但花了很长时间。 Stackoverflow 和其他地方的各种线程帮助我想出了它。这是在 Android M 上的一种解决方法,但效果很好。由于有人要求,所以我想如果它可以使任何人受益,我应该将其发布在这里。

    现在已经有一段时间了,我不记得所有细节了,但 CustomViewGroup 是覆盖主 ViewGroup 的类,它检测到用户从顶部滑动以显示状态栏。但我们不想显示它,因此检测到用户的拦截并忽略任何进一步的操作,即 Android 操作系统不会收到打开隐藏状态栏的信号。

    然后还包括显示和隐藏状态栏的方法,您可以将它们复制/粘贴到您想要显示/隐藏状态栏的代码中。

    /**
     * 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;
        //http://stackoverflow.com/questions/1016896/get-screen-dimensions-in-pixels
        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我该如何解决
    • 对 api >26 使用 TYPE_APPLICATION_OVERLAY 而不是 TYPE_SYSTEM_ERROR
    • Android OS won't get a signal to open the hidden status bar,到底如何?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    相关资源
    最近更新 更多