Android编程实现禁止状态栏下拉的方法详解

本文实例讲述了Android编程实现禁止状态栏下拉的方法。分享给大家供大家参考,具体如下:

简介

项目需求APP全屏时,要禁止状态栏的下拉,这个应该是一个普遍的需求了吧,但Android系统没有直接提供给普通APP直接调用的接口。那么我们只能自己想办法增加接口去实现该功能了。

具体实现方法

1. 修改SystemUI

路径:==/frameworks/base/packages/SystemUI//src/com/android/systemui/statusbar/phone/PhoneStatusBar.Java==

通过在PhoneStatusBar.java类中注册一个广播的方式来实现状态栏的禁用和解除,其核心方法就是调用了disable()方法。disable()是SystemUI自定义的方法,感兴趣的同学可以去看其具体实现。

下面来看下我们在SystemUI中的具体实现代码:

@@ -494,6 +494,31 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
                                                            }
+    //add steven zhang by 20160701
+    private BroadcastReceiver mStatusShowHide = new BroadcastReceiver() {
+
+        @Override
+        public void onReceive(final Context context, Intent intent) {
+            // TODO Auto-generated method stub
+            String action = intent.getAction();
+
+            if ("com.aura.statusbar.SHOW_OR_HIDE".equals(action)) {
+                // StatusBarManager.DISABLE_NONE
+                // StatusBarManager.DISABLE_EXPAND
+                final int mode = intent.getIntExtra("mode", StatusBarManager.DISABLE_NONE);
+                if (mNavigationBarView != null) {
+                    mHandler.post(new Runnable() {
+
+                        @Override
+                        public void run() {
+
+                            disable(mode);
+                        }
+                    });
+                }
+            }
+        }
+    };
     //micheal add the Broadcast interface for Control the wifi sleep mode change begin 20150514
     private BroadcastReceiver wifiSleepModeChangeReceiver = new BroadcastReceiver(){
       @Override
@@ -519,6 +544,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
   // ================================================================================
   protected PhoneStatusBarView makeStatusBarView() {
     final Context context = mContext;
+        // add steven zhang by 20160701
+        IntentFilter statusFilter = new IntentFilter();
+        statusFilter.addAction("com.aura.statusbar.SHOW_OR_HIDE");
+        context.registerReceiver(mStatusShowHide, statusFilter);

既然显示隐藏的广播我们已经注册好了,那么看下我们在APP中的具体调用吧。

@Override
protected void onResume() {
    super.onResume();
    Intent i = new Intent("com.aura.statusbar.SHOW_OR_HIDE");
    i.putExtra("mode", StatusBarManager.DISABLE_EXPAND);
    sendBroadcast(i);
}
@Override
protected void onPause() {
    super.onPause();
    Intent i = new Intent("com.aura.statusbar.SHOW_OR_HIDE");
    i.putExtra("mode", StatusBarManager.DISABLE_NONE);
    sendBroadcast(i);
}

在Activity中重写onResumeonPause方法实现状态栏的禁用和解除禁用。另:StatusBarManager是一个隐藏类,所以调用的时候可能导入不了包会报错,最简单的方法就是之间用数值替换,下面列出对应关系。

public static final int DISABLE_EXPAND       = 0x00010000;
public static final int DISABLE_NOTIFICATION_ICONS = 0x00020000;
public static final int DISABLE_NOTIFICATION_ALERTS = 0x00040000;
public static final int DISABLE_NOTIFICATION_TICKER = 0x00080000;
public static final int DISABLE_SYSTEM_INFO     = 0x00100000;
public static final int DISABLE_HOME        = 0x00200000;
public static final int DISABLE_RECENT       = 0x01000000;
public static final int DISABLE_BACK        = 0x00400000;
public static final int DISABLE_CLOCK        = 0x00800000;
public static final int DISABLE_SEARCH       = 0x02000000;
public static final int DISABLE_NONE        = 0x00000000;
public static final int DISABLE_NAVIGATION =
    View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_RECENT;
public static final int DISABLE_MASK = DISABLE_EXPAND | DISABLE_NOTIFICATION_ICONS
    | DISABLE_NOTIFICATION_ALERTS | DISABLE_NOTIFICATION_TICKER
    | DISABLE_SYSTEM_INFO | DISABLE_RECENT | DISABLE_HOME | DISABLE_BACK | DISABLE_CLOCK
    | DISABLE_SEARCH;

所以不能引用StatusBarManager的同学之间使用其数值是一样的。如果有源码的朋友,可以使用系统编译的后framework jar包作为APP的lib就可以直接使用StatusBarManager方法了。其路径为/out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/classes.jar。将classes.jar改为framework.jar导入工程就OK了。

通过上面的步骤我们知道最关键的就是调用PhoneStatusBar中disable()方法,我们这里是以广播的方式实现的,任何有新方法的同学可以脑洞大开,只要能实现调用到disable()就可以禁用状态栏。

2.修改PhoneWindowManager

路径:==/frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java==

// monitor for system gestures
mSystemGestures = new SystemGesturesPointerEventListener(context,
new SystemGesturesPointerEventListener.Callbacks() {
  @Override
  public void onSwipeFromTop() {
    if (isGestureIsolated())
      return;
    if (mStatusBar != null) {
      requestTransientBars(mStatusBar);
    }
  }
  @Override
  public void onSwipeFromBottom() {
    if (isGestureIsolated())
      return;
    if (mNavigationBar != null && mNavigationBarOnBottom) {
      requestTransientBars(mNavigationBar);
    }
  }
  @Override
  public void onSwipeFromRight() {
    if (isGestureIsolated())
      return;
    if (mNavigationBar != null && !mNavigationBarOnBottom) {
      requestTransientBars(mNavigationBar);
    }
  }
  @Override
  public void onDebug() {
    // no-op
  }
  private boolean isGestureIsolated() {
    boolean ret = false;
    ret = Settings.System.getInt(mContext.getContentResolver(),"status_bar_disabled", 0) == 1;
    return ret;
  }
});

SystemGesturesPointerEventListener.Callbacks的方法中增加一个判断函数isGestureIsolated()用于判断是否支持其对应的手势操作。在这里特别说明一下,在网上找到方法用

private boolean isGestureIsolated() {
    boolean ret = false;
    WindowState win = mFocusedWindow != null ? mFocusedWindow:mTopFullscreenOpaqueWindowState;
    if (win != null && (win.getSystemUiVisibility() & View.SYSTEM_UI_FLAG_IMMERSIVE_GESTURE_ISOLATED) != 0)
      ret = true;
    else
      ret = false;
    return ret;
}

getSystemUiVisibility()这种方式做判断的时候,获取到的win不一定是当前activity的,有时候是statusbar的,所以这样的效果不是很好,经常会下拉出状态栏,于是就有了

Settings.System.getInt(mContext.getContentResolver(),"status_bar_disabled", 0) == 1;

做判断的方法,用这种方式有一个好处就是非常直接,需要它禁止下拉的时候,就调用

Settings.System.putInt(getContentResolver(), "status_bar_disabled", 1);

就OK了,解除禁止的时候调用

Settings.System.putInt(getContentResolver(), "status_bar_disabled", 0);

看下Activity中的具体调用

@Override
protected void onResume() {
    super.onResume();
    //禁止下拉
    Settings.System.putInt(getContentResolver(), "status_bar_disabled", 1);
}
@Override
protected void onPause() {
    super.onPause();
    //解除禁止
    Settings.System.putInt(getContentResolver(), "status_bar_disabled", 0);
}

在AndroidManifest.xml中声明相应的权限

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

网上还有修改PhoneWindowManager中的adjustSystemUiVisibilityLw方法的,如:

@Override
public int adjustSystemUiVisibilityLw(int visibility){
    if (Settings.System.getInt(mContext.getContentResolver(),"status_bar_disabled", 0) == 0) {
      mStatusBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
    }
    mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility);
    // Reset any bits in mForceClearingStatusBarVisibility that
    // are now clear.
    mResettingSystemUiFlags &= visibility;
    // Clear any bits in the new visibility that are currently being
    // force cleared, before reporting it.
    return visibility & ~mResettingSystemUiFlags
        & ~mForceClearedSystemUiFlags;
}

在adjustSystemUiVisibilityLw增加一个标志的判断,但这种实现的效果也不是很好,还是会出现下拉能拉下来的情况。

综上所叙,修改PhoneWindowManager实现禁止下拉的方法还是在SystemGesturesPointerEventListener.Callbacks中增加一个内部方法,这个内部方法使用标志位的形式来判断是否支持状态栏下拉。

3. 使用StatusBarManager中方法

因为StatusBarManager是隐藏方法,所以要在IDE中直接使用的话要导入framework jar包,怎么找到framework jar在1. 修改SystemUI中有说过,这里就不重复了。直接上代码:

1.在AndroidManifest.xml中声明相应的权限

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

网上有文章说要声明

android : sharedUserId="android.uid.system"

亲自测试没有加上面这行代码,也是可以使用的。

2. 在Activity中的引用

@Override
protected void onResume() {
    super.onResume();
    StatusBarManager statusBarManager = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
    statusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
}
@Override
protected void onPause() {
    super.onPause();
    StatusBarManager statusBarManager = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
    statusBarManager.disable(StatusBarManager.DISABLE_NONE);
}

1.是使用系统签名,编译为系统app

java -jar signapk.jar platform.x509.pem platform.pk8 TestDemo.apk TestDemoNew.apk

TestDemoNew.apk就是系统签名后的apk,然后push到/system/app/目录下就ok了。关于签名的知识就不多说了,可自行找到相关资料。

下面看下原生系统中电话处理禁止下拉的做法,代码如下:

路径:==/packages/apps/Phone/src/com/android/phone/NotificationMgr.java==

/**
 * Updates the status bar to reflect the current desired state.
 */
private void updateStatusBar() {
  int state = StatusBarManager.DISABLE_NONE;
  if (!mIsExpandedViewEnabled) {
    state |= StatusBarManager.DISABLE_EXPAND;
  }
  if (!mIsNotificationEnabled) {
    state |= StatusBarManager.DISABLE_NOTIFICATION_ALERTS;
  }
  if (!mIsSystemBarNavigationEnabled) {
    // Disable *all* possible navigation via the system bar.
    state |= StatusBarManager.DISABLE_HOME;
    state |= StatusBarManager.DISABLE_RECENT;
    state |= StatusBarManager.DISABLE_BACK;
  }
  if (DBG) log("updateStatusBar: state = 0x" + Integer.toHexString(state));
  mStatusBarManager.disable(state);
}

从这个方法中我们知道系统禁用状态栏的方法就是调用StatusBarManager实现的。

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android开发入门与进阶教程》、《Android多媒体操作技巧汇总(音频,视频,录音等)》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

(0)

相关推荐

  • Android 去掉状态栏的方法汇总

    在实际的应用程序开发中,我们有时需要把 Activity 设置成全屏显示,一般情况下,可以通过两种方式来设置全屏显示效果: 其一,通过在代码中可以设置, 其二,通过manifest配置文件来设置全屏. 其一:在代码onCreate里面setContentView之前设置(如下) view plaincopy to clipboardprint? public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstan

  • android 动态控制状态栏显示和隐藏的方法实例

    方法一:(经试验无效,但网上广为流传,也许是我使用方法不当,有待进一步验证--) android想要应用运行时全屏有一种方法是在activity的onCreat方法中加入如下代码:getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,                 WindowManager.LayoutParams.FLAG_FULLSCREEN);并且需要在setContentView()之前,否则无效过.从这么多的

  • Android编程实现禁止StatusBar下拉的方法

    本文实例讲述了Android编程实现禁止StatusBar下拉的方法.分享给大家供大家参考,具体如下: Android中有许多隐藏的Service,StatusBarManager就是其中一个,在Context.java中可以看到: /** * Use with {@link #getSystemService} to retrieve a {@link * android.app.StatusBarManager} for interacting with the status bar. *

  • Android之沉浸式状态栏的实现方法、状态栏透明

    现在越来越多的软件都开始使用沉浸式状态栏了,下面总结一下沉浸式状态栏的两种使用方法 注意!沉浸式状态栏只支持安卓4.4及以上的版本 状态栏:4.4上是渐变色,5.0上是完全透明,本文模拟器为4.4演示 效果图: 注意!两种方法的区别: 第一种:为顶部栏跟随当前activity的布局文件的背景的颜色,使用方便,不过也有点问题就是,如果有底部虚拟导航键的话,导航键的背景跟顶部的颜色一样,比如: 第二种:是通过设置顶部栏的颜色来显示的,可以解决第一种的不足,比如: 第一种使用方法: 第一.首先在val

  • Android 实现沉浸式状态栏的方法

    沉浸式状态栏的来源就是很多手机用的是实体按键,没有虚拟键,于是开了沉浸模式就只有状态栏消失了.于是沉浸模式成了沉浸式状态栏. 我们先来看下具体的效果 开启沉浸模式后,状态栏消失,从顶部向下滑动,状态栏出现,退出沉浸模式,状态栏也出现了. 我们的代码基于前一篇文章.首先是两个开启沉浸模式和关闭沉浸模式的函数 @SuppressLint("NewApi") public static void hideSystemUI(View view) { view.setSystemUiVisibi

  • Android 状态栏虚拟导航键透明效果的实现方法

    状态栏和虚拟导航键 4.4上半透明,5.0以上可以全透明 先上效果 4.4 半透明效果 5.0及以上 全透明效果 上代码 MainActivity代码 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 隐藏标题栏 supportReque

  • Android 4.4以上"沉浸式"状态栏效果的实现方法

    什么是沉浸式状态栏? 沉浸式状态栏意思指状态栏的颜色随着软件颜色而改变,使状态栏和软件颜色保持一致,沉浸其中!当我们打开应用程序时,不会再因为看到应用程序和状态栏的黑边相隔开而感到十分难看.沉浸式状态栏由于其能给用户群体带来极佳的用户体验,已经在越来越多的应用上得到了体现. 实现原理 从4.4后系统增加了透明状态栏的特性WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS 一旦添加上这个属性后,那么布局中的内容DecorView就会自动填充到状态栏

  • Android开发实现应用层面屏蔽状态栏的方法小结

    本文实例讲述了Android开发实现应用层面屏蔽状态栏的方法.分享给大家供大家参考,具体如下: 一.由于StatusBarManager在SDK中没有提供,所以需要使用反射来调用该类的方法 代码部分如下: Object service = getSystemService("statusbar"); try { Class <?> statusBarManager = Class.forName("Android.app.StatusBarManager"

  • Android 取得状态栏、任务栏高度的小例子

    复制代码 代码如下: package com.aslibra.test; import android.app.Activity; import android.graphics.Rect; import android.os.Bundle; import android.util.Log; import android.view.Window; import android.widget.ImageView; public class test extends Activity {   Ima

  • Android实现的状态栏定制和修改方法

    本文实例讲述了Android实现的状态栏定制和修改方法.分享给大家供大家参考.具体如下: 大家都知道定制在android开发中的重要性,因为通过定制,你才能制造出差异化的产品,才能满足更多消费者的需求, 像HTC生产的手机都通过了深层次的二次开发,今天我也来分享一下我的状态栏定制. 废话不说了,直接上图: 主要更换了背景,文字颜色以及icon的显示顺序. 2. 关键代码部分 a) 代码在系统中的位置 status bar 的相关代码位于:frameworks/base/services/java

  • Android自定义状态栏颜色与应用标题栏颜色一致

    每次看IOS上的应用,应用中状态栏的颜色总能与应用标题栏颜色保持一致,用户体验很不错,对于这种效果,像我这种好奇心强的人就会去看看那安卓是否可以呢?若是在安卓4.4之前,答案是否定的,但在4.4之后,谷歌允许开发者自定义状态栏背景颜色啦,这是个不错的体验!若你手机上安装有最新版的qq,并且你的安卓SDK版本是4.4及以上,你可以看下它的效果: 实现此功能有两种方法: 1.在xml中设置主题或自定义style: Theme.Holo.Light.NoActionBar.TranslucentDec

随机推荐