android4.3 SDK控制动态显示导航栏(NavigationBar)

//--------------------------------------------------------------------------------------------

// 作者:longtian635241

// 发布日期:2015-08-25

// 最后修改:2015-08-25

//http://blog.csdn.net/longtian635241

//----------------------------------------------------------------------------------------------

1、android4.0开始应用中有提供API:view的setSystemUiVisibility(int visibility)方法实现动态操作状态栏;

这个借口的本意是提供给我们看视频时一段时间不操作而全屏,但触摸导航栏又出来了!(入口怀疑是被系统劫持了触摸事件)

2、网上也有用广播去隐藏导航栏的,具体没有测试如:

http://blog.csdn.net/hdwslss/article/details/39497519

3、永久隐藏的方法

     3.1 在/system/build.prop或default.prop中添加

 qemu.hw.mainkeys=1
3.2 修改Z:\wk\myandroid\frameworks\base\core\res\res\values\config.xml(原始系统)如我的平台为freescale的imx6dq,修改Z:\wk\myandroid\device\fsl\sabresd_6dq\overlay\frameworks\base\core\res\res\values\config.xml中的
<bool name="config_showNavigationBar">true</bool>将true改为false!
3.3、如果隐藏了NavBar,将可能导致应用中actionBar上的overflow按键消失, 如果不显示

Android-4.4之前,软的Menu键和NavBar的显示有关系,如果不显示NavBar,通常意味着有硬件的TP,在软件上就不会显示Menu键;如果NavBar要显示,通常说明没有硬件TP,所以默认需要在ActionBar上把Menu键显示出来

但是,当有硬件TP存在,又没有Menu键的时候,怎么办?


在ViewConfiguration.java中,sHasPermanentMenuKey代表的就是是否有硬件的TP

[java] view plaincopy
  1. sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar();  

如果sHasPermanentMenuKey为false,表示没有硬件的TP,这个时候就会把Menu键强制的显示出来,可以做这样的类似的修改:

[java] view plaincopy
  1. sHasPermanentMenuKey = !wm.hasSystemNavBar() && !wm.hasNavigationBar() && false;  
方法二:
如果在app中显示,又不方便改系统时可用如下方法:
@Override 
protected void onCreate(Bundle savedInstanceState) {  
    ......  
    setOverflowShowingAlways();  
}  
 
private void setOverflowShowingAlways() {  
    try {  
        ViewConfiguration config = ViewConfiguration.get(this);  
        Field menuKeyField = ViewConfiguration.class.getDeclaredField("sHasPermanentMenuKey");  
        menuKeyField.setAccessible(true);  
        menuKeyField.setBoolean(config, false);  
    } catch (Exception e) {  
        e.printStackTrace();  
    }  
}

4、动态隐藏修改
4.1 systemUI.apk启动过程:http://blog.csdn.net/andyhuabing/article/details/12851825

  4.2 最后确定frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java,在调用setSystemUiVisibility后会调用private int updateSystemUiVisibilityLw()其在finishPostLayoutPolicyLw中调用!可以看到隐藏状态栏的代码!
        4.3 寻找劫持触摸事件,由按键知道一般会在interceptKeyBeforeDispatching去劫持分发,但是么有发现和导航栏有关的信息,再次搜所输入事件接收器InputEventReceiver,这是我们发现HideNavInputEventReceiver这个类,它就是劫持输入事件的类!在其下面初始化了一个变量:
final InputEventReceiver.Factory mHideNavInputEventReceiverFactory =
            new InputEventReceiver.Factory() {
        @Override
        public InputEventReceiver createInputEventReceiver(
                InputChannel inputChannel, Looper looper) {
            return new HideNavInputEventReceiver(inputChannel, looper);
        }
    };
上面变量的使用在:
public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
                              int displayRotation) {
。。。。。。。。。。。。。。。。。。
  if (navVisible) {
                if (mHideNavFakeWindow != null) {
                    mHideNavFakeWindow.dismiss();
                    mHideNavFakeWindow = null;
                }
            } else if (mHideNavFakeWindow == null) {
                mHideNavFakeWindow = mWindowManagerFuncs.addFakeWindow(
                        mHandler.getLooper(), mHideNavInputEventReceiverFactory,
                        "hidden nav", WindowManager.LayoutParams.TYPE_HIDDEN_NAV_CONSUMER,
                        0, false, false, true);//此处被调用
            }


            // For purposes of positioning and showing the nav bar, if we have
            // decided that it can't be hidden (because of the screen aspect ratio),
            // then take that into account.
            navVisible |= !mCanHideNavigationBar;
。。。。。。。。。。。。。。
}
当然很自然到注释他,果然注释即可!
5、改完上面即可用view的setSystemUiVisibility(int visibility)方法实现隐藏导航栏,但是如你想运用全屏去隐藏状态栏和导航栏还得修改:
private int updateSystemUiVisibilityLw() {
。。。。。。。。。。。。。。。。。。
 int tmpVisibility = mFocusedWindow.getSystemUiVisibility()
                & ~mResettingSystemUiFlags
                & ~mForceClearedSystemUiFlags;
//add by hcm
if(mTopIsFullscreen){
tmpVisibility = 2;
}
//add by end
。。。。。。。。。。。。。。。。。。。}
这样就可运用如下方法实现真正的全屏

a、在AndroidManifest.xml的配置文件里面的<activity>标签添加属性:

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

b、在Activity的onCreate()方法中的super()和setContentView()两个方法之间加入下面两条语句:

this.requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题栏

this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//去掉信息栏

6、其他方法思路
     我们实时更新隐藏,一般会想到广播,但是参考phonewindowmanager.java,可以想到Setting里面的设置时怎么修改,设置在phonewindowmanager里面写了一个 class SettingsObserver extends ContentObserver 的类,所以我们也可以参考此思路来实时更新!
更新的函数参考:http://www.16rd.com/home.php?mod=space&uid=6514&do=blog&id=83

7、FakeWindow扩展
http://m.blog.csdn.net/blog/sundesheng125/24478833

其他参考资料:
http://www.cnblogs.com/android100/archive/2012/06/20/2556577.html
http://www.myexception.cn/android/1307491.html
http://blog.csdn.net/chenqian_lj/article/details/17719903
http://blog.csdn.net/chaihuasong/article/details/31741659
http://blog.csdn.net/chenqian_lj/article/details/22388367


你可能感兴趣的:(NavigationBar,导航栏,Android4.3)