如何在Android中禁用状态栏点击和下拉?

Naz*_*MMF 9 android

如何禁用Android中的状态栏单击和下拉?我尝试了很多东西,但这不起作用.

Dav*_*man 14

在我看来,有两种选择:

选项1:您可以在状态栏上方放置一个窗口以禁用任何触摸或下拉.

选项2:您还可以覆盖OnWindowFocusChanged()方法,以在显示后立即关闭通知面板.

如何:

选项1:在您的活动中定义以下方法(preventStatusBarExpansion)和类(CustomViewGroup).

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

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", "**********Intercepted");
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

并在活动的onCreate方法中调用preventStatusBarExpansion方法.完成!

选项2:首先,将以下权限添加到Androidmanifest.xml文件中:

<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
Run Code Online (Sandbox Code Playgroud)

其次,在您的活动中定义以下类范围变量:

// To keep track of activity's window focus
boolean currentFocus;

// To keep track of activity's foreground/background status
boolean isPaused;

Handler collapseNotificationHandler;
Run Code Online (Sandbox Code Playgroud)

第三,重写onWindowFocusChanged(boolean):

@Override
public void onWindowFocusChanged(boolean hasFocus) {

    currentFocus = hasFocus;

    if (!hasFocus) {

        // Method that handles loss of window focus
        collapseNow();
    }
}
Run Code Online (Sandbox Code Playgroud)

第四,定义collapseNow(); 方法:

public void collapseNow() {

    // Initialize 'collapseNotificationHandler'
    if (collapseNotificationHandler == null) {
        collapseNotificationHandler = new Handler();
    }

    // If window focus has been lost && activity is not in a paused state
    // Its a valid check because showing of notification panel
    // steals the focus from current activity's window, but does not 
    // 'pause' the activity
    if (!currentFocus && !isPaused) {

        // Post a Runnable with some delay - currently set to 300 ms
        collapseNotificationHandler.postDelayed(new Runnable() {

            @Override
            public void run() {

                // Use reflection to trigger a method from 'StatusBarManager'                

                Object statusBarService = getSystemService("statusbar");
                Class<?> statusBarManager = null;

                try {
                    statusBarManager = Class.forName("android.app.StatusBarManager");
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }

                Method collapseStatusBar = null;

                try {

                    // Prior to API 17, the method to call is 'collapse()'
                    // API 17 onwards, the method to call is `collapsePanels()`

                    if (Build.VERSION.SDK_INT > 16) {
                        collapseStatusBar = statusBarManager .getMethod("collapsePanels");
                    } else {
                        collapseStatusBar = statusBarManager .getMethod("collapse");
                    }
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                }

                collapseStatusBar.setAccessible(true);

                try {
                    collapseStatusBar.invoke(statusBarService);
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

                // Check if the window focus has been returned
                // If it hasn't been returned, post this Runnable again
                // Currently, the delay is 100 ms. You can change this
                // value to suit your needs.
                if (!currentFocus && !isPaused) {
                    collapseNotificationHandler.postDelayed(this, 100L);
                }

            }
        }, 300L);
    }   
}
Run Code Online (Sandbox Code Playgroud)

最后,重写onPause()和onResume方法:

@Override
protected void onPause() {
    super.onPause();

    // Activity's been paused      
    isPaused = true;
}

@Override
protected void onResume() {
    super.onResume();

    // Activity's been resumed
    isPaused = false;
}
Run Code Online (Sandbox Code Playgroud)

完成!

注意:在将应用程序置于kiosk模式时,我使用了第一个选项,该模式根本不显示通知面板.另一方面,第二个选项运行良好,但它允许通知面板显示一小段时间,用户可以快速单击通知面板顶部的设置图标以退出自助服务终端模式.

希望这会帮助你.干杯!

  • 非常详细的答案.但是,当运行第一个选项时,我得到RuntimeException,原因是:---无法添加窗口android.view.ViewRootImpl$W@38883eaa - 此窗口类型的权限被拒绝---有关如何使其工作的任何想法? (3认同)
  • 这在Android Oreo中无效 (3认同)