防止状态栏出现android(修改)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25284233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:18:27  来源:igfitidea点击:

Prevent status bar for appearing android (modified)

androidstatusbarkiosk

提问by Abhimaan

I am implementing a kiosk mode application and i have successfully made the application full-screen without status bar appearance post 4.3 but unable to hide status bar in 4.3 and 4.4 as status-bar appears when we swipe down at the top of the screen.

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

I have tried to make it full screen by

我试图让它全屏

  • speciflying the full screen theme in manifest
  • setting window Flags ie setFlags
  • setSystemUiVisibility
  • 在清单中指定全屏主题
  • 设置窗口标志即 setFlags
  • 设置系统可见性

Possible duplicate but no concrete solution found

可能重复但没有找到具体的解决方案

Permanently hide Android Status Bar

永久隐藏 Android 状态栏

Finally the thing i want is, how to hide status bar permanently in an activity?? in android 4.3,4.4,5,6versions

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

回答by Abhimaan

We could not prevent the status appearing in full screen mode in kitkat devices, so made a hack which still suits the requirement ie block the status bar from expanding.

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

For that to work, the app was not made full screen. We put a overlay over status bar and consumed all input events. It prevented the status from expanding.

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

note:

笔记:

  • customViewGroup is custom class which extends any layout(frame,relative layout etc) and consumes touch event.
  • to consume touch event override the onInterceptTouchEvent method of the view group and return true
  • customViewGroup 是自定义类,它扩展任何布局(框架、相对布局等)并使用触摸事件。
  • 消费触摸事件覆盖视图组的onInterceptTouchEvent方法并返回true

Updated

更新

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

customViewGroup implementation

自定义视图组实现

Code :

代码 :

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

回答by Alexey Ozerov

In Android M you have to get an extra permission for making overlays. android.permission.SYSTEM_ALERT_WINDOWis not enough! So I used the code from the answer of Abhimaan within disableStatusBar()and had to make an intent to open the right settings dialog. I also added removing view in onDestroy()in order to enable status bar when the app exits. I also reduced the overlay height to 40 as it seems to be enough. Code works with 5.1 and 6.0 here.

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

回答by zeeshan

For a project I worked on I had found a solution for this but it took a long time. Various threads on Stackoverflow and elsewhere helped me to come up with it. It was a work around on Android M but it worked perfectly. As someone asked for it so I thought I should post it here if it can benefit anyone.

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

Now that its been a while, I don't remember all the details, but the CustomViewGroup is the class which overrides the main ViewGroup, and detects that a user has swiped from top to show the status bar. But we didn't want to show it, so the user's intercept was detected and any further action was ignored, i.e. Android OS won't get a signal to open the hidden status bar.

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

And then the methods to show and hide the status bar are also included which you can copy/paste as is in your code where you want to show/hide the status bar.

然后还包括显示和隐藏状态栏的方法,您可以按原样复制/粘贴在要显示/隐藏状态栏的代码中。

/**
 * 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);
}