如果你有这样的需求:用户进入你的app以后,所有的操作都是你的app中设定的,用户不可以拥有系统设置等行为的能力。然而,android系统,可以通过从顶部往下拉,从而得到一个通知和快速系统设置的页面:

因此,现在你想禁止它弹出,怎么办呢?
我不知道在app中怎么做,但是如果你们的处境像我一样:Android系统是一个针对特殊平台定制的,它一旦启动就进入特定的功能页面,并且不允许用户有进入系统设置的能力,那么您可以像下面这样,直接在系统代码中进行修改。

分析如何解决问题

使用Android device monitor工具,我们可以看到Android 状态栏的布局,我们会发现,平时我们看到的状态栏(如下图所示)是由PhoneStatusBarView负责绘制个管理的:

结合我们的操作,当我们点击状态栏或者下拉的时候,都会出现通知界面。而点击和下拉都是触摸事件,因此,理所当然的,我们会想到在PhoneStatusBarView的onTouchEvent中处理相应的逻辑。onTouchEvent定义在frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\PhoneStatusBarView.java中:

    @Overridepublic boolean onTouchEvent(MotionEvent event) {boolean barConsumedEvent = mBar.interceptTouchEvent(event);if (DEBUG_GESTURES) {if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {EventLog.writeEvent(EventLogTags.SYSUI_PANELBAR_TOUCH,event.getActionMasked(), (int) event.getX(), (int) event.getY(),barConsumedEvent ? 1 : 0);}}return barConsumedEvent || super.onTouchEvent(event);}

它似乎什么都没有做…然而不要忽视了,它调用了super.onTouchEvent(event)方法。PhoneStatusBarView继承了PanelBar类,这个类继承自PanelBar类。因此,super.onTouchEvent就是调用PanelBar中的onTouchEvent方法,PanelBar也在frameworks\base\packages\SystemUI\src\com\android\systemui\statusbar\phone\目录下:

   @Overridepublic boolean onTouchEvent(MotionEvent event) {// Allow subclasses to implement enable/disable semanticsif (!panelsEnabled()) {if (event.getAction() == MotionEvent.ACTION_DOWN) {Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",(int) event.getX(), (int) event.getY()));}return false;}// figure out which panel needs to be talked to hereif (event.getAction() == MotionEvent.ACTION_DOWN) {final PanelView panel = selectPanelForTouch(event);if (panel == null) {// panel is not there, so we'll eat the gestureLog.v(TAG, String.format("onTouch: no panel for touch at (%d,%d)",(int) event.getX(), (int) event.getY()));mTouchingPanel = null;return true;}boolean enabled = panel.isEnabled();if (DEBUG) LOG("PanelBar.onTouch: state=%d ACTION_DOWN: panel %s %s", mState, panel,(enabled ? "" : " (disabled)"));if (!enabled) {// panel is disabled, so we'll eat the gestureLog.v(TAG, String.format("onTouch: panel (%s) is disabled, ignoring touch at (%d,%d)",panel, (int) event.getX(), (int) event.getY()));mTouchingPanel = null;return true;}startOpeningPanel(panel);}final boolean result = mTouchingPanel != null? mTouchingPanel.onTouchEvent(event): true;return result;}

从函数的名字猜测,startOpeningPanel方法似乎就是弹出下拉菜单的入口,把它注释掉,重新编译SystemUI模块,然后替换/system/priv-app/SystemUI/SystemUI.apk,重启系统,就发现无论你是点击还是下拉屏幕顶部,都不会出现下拉也面了。
我们不妨简单分析下这里:
startOpeningPanel接收一个panel作为参数,而这个panel则是selectPanelForTouch(event);方法返回的。
PhoneStatusBarView中覆写了该方法:

@Overridepublic PanelView selectPanelForTouch(MotionEvent touch) {// No double swiping. If either panel is open, nothing else can be pulled down.return mNotificationPanel.getExpandedHeight() > 0? null: mNotificationPanel;}

可以看到,这里返回的是mNotificationPanel。是的它就是下面的样子:

既然我们在这里得到了这个页面,startOpeningPanel应该就是将这个页面呈现出来吧。
startOpeningPanel如下:

    // called from PanelView when self-expanding, toopublic void startOpeningPanel(PanelView panel) {if (DEBUG) LOG("startOpeningPanel: " + panel);mTouchingPanel = panel;mPanelHolder.setSelectedPanel(mTouchingPanel);for (PanelView pv : mPanels) {if (pv != panel) {pv.collapse(false /* delayed */);}}}

对所有的PanelView ,调用它的collapse方法,改方法如下:

    public void collapse(boolean delayed) {if (DEBUG) logf("collapse: " + this);if (mPeekPending || mPeekAnimator != null) {mCollapseAfterPeek = true;if (mPeekPending) {// We know that the whole gesture is just a peek triggered by a simple click, so// better start it now.removeCallbacks(mPeekRunnable);mPeekRunnable.run();}} else if (!isFullyCollapsed() && !mTracking && !mClosing) {cancelHeightAnimator();mClosing = true;notifyExpandingStarted();if (delayed) {postDelayed(mFlingCollapseRunnable, 120);} else {fling(0, false /* expand */);}}}

如果我们正在下拉,同时下拉的动画不为空,那么会调用mPeekRunnable.run();

    private Runnable mPeekRunnable = new Runnable() {@Overridepublic void run() {mPeekPending = false;runPeekAnimation();}};

调用runPeekAnimation:

   private void runPeekAnimation() {mPeekHeight = getPeekHeight();if (DEBUG) logf("peek to height=%.1f", mPeekHeight);if (mHeightAnimator != null) {return;}mPeekAnimator = ObjectAnimator.ofFloat(this, "expandedHeight", mPeekHeight).setDuration(250);mPeekAnimator.setInterpolator(mLinearOutSlowInInterpolator);mPeekAnimator.addListener(new AnimatorListenerAdapter() {private boolean mCancelled;@Overridepublic void onAnimationCancel(Animator animation) {mCancelled = true;}@Overridepublic void onAnimationEnd(Animator animation) {mPeekAnimator = null;if (mCollapseAfterPeek && !mCancelled) {postOnAnimation(new Runnable() {@Overridepublic void run() {collapse(false /* delayed */);}});}mCollapseAfterPeek = false;}});notifyExpandingStarted();mPeekAnimator.start();mJustPeeked = true;}

这里使用了属性动画将它移动到指定的高度上。

Android 禁止状态栏下拉相关推荐

  1. Android 9.0 SystemUI 锁屏界面禁止状态栏下拉

    目录 1.概述 2.SystemUI 锁屏界面禁止状态栏下拉的核心类 3.SystemUI 锁屏界面禁止状

  2. 安卓游戏时禁止状态栏下拉_Android手机屏蔽状态栏下拉

    [声明:]本文是作者(蘑菇v5)原创,版权归作者 蘑菇v5所有,侵权必究.本文首发在简书.如若转发,请注明作者和来源地址!未经授权,严禁私自转载! 一.前言: 如果是系统级应用,也就是手机厂家植入的应 ...

  3. 安卓游戏时禁止状态栏下拉,如何在Android中禁用通知栏下拉菜单?

    I am building a new lock screen for Android, but I am unable to lock the notification bar from pulli ...

  4. Android 10 禁止SystemUI 下拉状态栏和通知栏

    1.未锁屏时禁止状态栏和通知栏下拉 代码路径: frameworks/base/packages/SystemUI/src/com/android/systemui/keyguard/Keyguard ...

  5. Android实现系统下拉栏的消息提示——Notification

    Android实现系统下拉栏的消息提示--Notification 系统默认样式 默认通知(通用) 效果图 按钮 <Button android:layout_width="match ...

  6. android加载时二级联动点击二级联动,Android实现联动下拉框二级地市联动下拉框功能...

    日常使用软件中,为了方便且规范输入,会使用到下拉框进行输入,如注册时生日选项,购物时的地址输入,都会用到下拉框,今日笔者为了巩固已学的知识,实现了二级联动下拉框用作回顾及分享给求知的新手. 思路/步骤 ...

  7. 微信中禁止网页下拉出现网页由XXX提供 【亲测有效】

    最近在开发过程中遇到新的需求:在微信公众号中禁止下拉出现我司域名,微信公众号中的域名是由微信内置浏览器根据网址自动读取,暂时不支持自定义功能.在无法更改的前提下,想到了禁止页面下拉的方法.于是有了以下 ...

  8. android自带下拉阻尼动画,android 有阻尼下拉刷新列表的实现方法

    本文将会介绍有阻尼下拉刷新列表的实现,先来看看效果预览: 这是下拉状态: 这是下拉松开手指后listView回滚到刷新状态时的样子: 1. 如何调用 虽然效果图看起来样子不太好看,主要是因为那个蓝色的 ...

  9. android 下拉刷新实现方式,Android RecyclerView设置下拉刷新的实现方法

    Android RecyclerView设置下拉刷新的实现方法 1 集成 SwipeRefreshLayout 1.1 xml布局文件中使用 android:id="@+id/refresh ...

最新文章

  1. FFT/NTT/FMT/FWT题目
  2. 使用Spring Boot和Kubernetes构建微服务架构
  3. 医疗器械监管系统总结
  4. CDialog 放到 CDockablePane里,总在外面显示?
  5. python安装 pip_多版本Python安装pip及pip版本管理终极教程
  6. 数学建模(5)---煤矸石堆积问题
  7. micropython入门教程-MicroPython入门教程之语法基础
  8. Win32 文件(2)
  9. 元素(Element)
  10. Oracle -- rollup函数
  11. Web版SSH客戶端Sshwifty
  12. Floyd + 传递闭包
  13. linux下安装sqlite3
  14. 单片机基础实验六则(汇编)
  15. 图片相似度判断-差异值哈希算法JAVA版
  16. 安卓手机连接Mac电脑可用的管理工具:Android File Transfer
  17. windows蓝牙编程—— 0 获取本地蓝牙的句柄和信息
  18. 海昇智:拼多多推广创意图如何才能做好?
  19. PS 学习笔记 15-橡皮擦工具组
  20. 关于Idea 下载Maven依赖时出现的 “unexpected markup <!d (position: START_DOCUMENT seen \r\n<!d... @2:4) “ 错误.

热门文章

  1. python 添加半透明水印_如何利用python给图片添加半透明水印
  2. bzoj 2876: [Noi2012]骑行川藏 二分+拉格朗日乘数法
  3. Vue2.0的三种常用传值方式、父传子、子传父、非父子组件传值
  4. Icon Font的转换
  5. pytdx 安装 初步使用
  6. matlab新手信号分析ppt,卡普课件 《信号与系统》matlab实现连续系统时域分析.ppt...
  7. 上网行为管理_上网行为管理如何预防以及屏蔽勒索病毒攻击
  8. EMV技术学习和研究(一)开篇
  9. Ansible秘钥认证
  10. windows10下Docker部署Kurento