禁用通知面板被拉下来

DDu*_*man 12 android android-notification-bar

我正在使用锁屏应用程序,我需要禁用下拉屏幕顶部的通知/状态栏的功能.有一个名为Holo Locker的应用程序,这个应用程序的作用是当用户从屏幕顶部向下拉时,它只是将条形设置回到屏幕顶部并且无法将抽屉拉下来.

我不知道从哪里开始.任何帮助都会很棒!谢谢!

Vik*_*ram 30

这可以使用反射.但是有很多问题.

无法检查通知面板是打开还是打开.所以,我们必须依靠Activity#onWindowFocusChanged(boolean).这就是问题的开始.

该方法的作用如下:

public void onWindowFocusChanged(boolean hasFocus)

当活动的当前窗口获得或失去焦点时调用.这是该活动对用户是否可见的最佳指标.

因此,我们必须找出一种方法来区分由于显示通知面板导致的焦点丢失和由于其他事件导致的焦点丢失.

一些会触发的事件onWindowFocusChanged(boolean):

  • 将活动发送到后台(用户切换应用程序或按下home按钮)时窗口焦点丢失

  • 由于Dialogs和PopupWindows在各自独立的窗口中打开,因此当显示这些窗口时,活动的窗口焦点将丢失.

  • 活动窗口失去焦点的另一个实例是单击微调器时,显示PopupWindow.

您的活动可能不必处理所有这些问题.以下示例处理它们的子集:

首先,您需要获得EXPAND_STATUS_BAR许可:

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

希望这接近你想要的.

注意:不幸的是,滑动通知栏并坚持下去时发生的闪烁是不可避免的.然而,可以使用处理器延迟的"更好"值来控制/改善其外观.这个问题也存在于Holo Locker应用程序中.


Nit*_*inM 7

        private void disablePullNotificationTouch() {
                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) (25 * getResources()
                        .getDisplayMetrics().scaledDensity);
                localLayoutParams.format = PixelFormat.RGBX_8888;
                customViewGroup view = new customViewGroup(this);
                manager.addView(view, localLayoutParams);
            }

    //Add this class in your project
    public 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)


ZZe*_*aNN 6

如果您只是想阻止用户打开状态,请尝试以下操作:

getWindow().addFlags(WindowManager.LayoutParams.[TYPE_SYSTEM_OVERLAY][1]);
Run Code Online (Sandbox Code Playgroud)

用法:

super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY);
setContentView(R.layout.your_layout);
Run Code Online (Sandbox Code Playgroud)

之前添加根据您的具体需要,您可以选择适当的WindowManager.LayoutParams.

希望这可以帮助.

  • 这段代码工作,但我需要我的活动按钮和其他布局在工作状态,但使用后我们无法做到这一点,谢谢 (3认同)
  • 这可以禁用通知栏,但它也会禁用其他所有内容。无论如何,我不认为这会是一个有用的解决方案。 (2认同)