android6.0 TV 添加自定义导航栏

Android TV 通常是用遥控器操作的,系统导航栏都是关闭的,但带触摸的TV就很有必要加上导航栏了。

1. 修改base/core/res/res/values/config.xml 

 base/core/res/res/values/config.xml

-    false
+    true

但是在TV 上屏通常是横屏的,手机上是竖屏的,仅仅打开上面这个设置,在TV 右边屏幕就会有一个黑条的导航栏,但没有图标,这时候就要把导航栏想办法改到屏幕下面,

2. base/services/core/java/com/android/server/policy/PhoneWindowManager.java

mNavigationBarOnBottom这个值决定导航条的位置,从名字就看的出来,true 的时候是底部,false在垂直右边,在TV 屏的1920x1080分辨率上这个值 为false,所以直接改为true

主要代码在setInitialDisplaySize, 和beginLayoutLw 这两个函数里,包括导航栏的位置,其实X,Y 坐标,长宽等到

            public void setInitialDisplaySize(Display display, int width, int height, int density) {

         ......................................
        mNavigationBarCanMove = width != height && shortSizeDp < 600; 这个值在setInitialDisplaySize函数里

                  ........................................

            public void beginLayoutLw(boolean isDefaultDisplay, int displayWidth, int displayHeight,
                              int displayRotation) {

...................................................
        mNavigationBarOnBottom = true;//(!mNavigationBarCanMove || displayWidth < displayHeight);
                if (mNavigationBarOnBottom) {
                    // It's a system nav bar or a portrait screen; nav bar goes on bottom.
                    int top = displayHeight - overscanBottom //计算底部显示的 Y 坐标
                            - 100; //mNavigationBarHeightForRotation[displayRotation]; 这个值是导航栏的宽度,在setInitialDisplaySize计算出来是0,实际Y 坐标top就是1080了,这样看不到了导航栏了,这里直接改成100
                    mTmpNavigationFrame.set(0, top, displayWidth, displayHeight - overscanBottom); //设置导航栏位置大小
                 ................................
                } else { 
                    // Landscape screen; nav bar goes to the right.
                    int left = displayWidth - overscanRight //计算在右边显示 X 坐标
                            - mNavigationBarWidthForRotation[displayRotation];
                    mTmpNavigationFrame.set(left, 0, displayWidth - overscanRight, displayHeight);
                   ................................

这样导航栏的三个图标就出来了

3. 修改base/packages/SystemUI/res/layout/navigation_bar.xml 实现自定义布局

 
  

在base/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java 文件的函数

public void onFinishInflate() {
        mRotatedViews[Surface.ROTATION_0] = 
        mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);

        mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);

        mRotatedViews[Surface.ROTATION_270] = mRotatedViews[Surface.ROTATION_90];

        mCurrentView = mRotatedViews[Surface.ROTATION_0]; TV 实际用的这个,所以布局里就只修改


                
                
            

注意:原来的返回,主页,任务的三个图标,代码里面还会引用图片的名字。如果要替换,最好把要换的图片名字改成原来的一样,直接覆盖替换,否则代码里还要同步修改。

4. 修改按钮事件

layout 文件里每个KeyButtonView 下有一个systemui:keyCode="4",对应按键映射码,最终会在KeyButtonView 里取出来赋值给mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0); 在sendEvent 里虚拟一个按键事件把这个按键发送出去。对于其他新增加的按钮事件,可以找一个没用到的按键当作该按钮的按键,比如定义为KEYCODE_F1, 在navigation_bar.xml  里修改systemui:keyCode="131",再在PhoneWindow.java 的onKeyDown里添加下面代码,就可以在任何界面都能打开该activity了

case KeyEvent.KEYCODE_F1: {
                Intent itent = new Intent();
                itent.setClassName("com.supera.board", "com.supera.board.MainActivity");
                mContext.startActivity(itent);
                return true;
            }

最终的自定义导航栏就如下面的效果

5. 修改导航栏的背景色

在navigation_bar.xml  里有 android:background="@drawable/system_bar_background" 这一行,实际光修改这里是不起作用的,参考https://blog.csdn.net/kongbaidepao/article/details/82118406 这篇文章,屏蔽掉一行android6.0 TV 添加自定义导航栏_第1张图片

再修改 android:background="@drawable/system_bar_background" 就可以自定义背景颜色了

6. 修改导航栏的动态隐藏显示

参考https://blog.csdn.net/way_ping_li/article/details/45727335 修改后,隐藏没有问题,但手势滑不出来导航栏,经过查找发现SystemGesturesPointerEventListener.java 文件里的screenWidth ,screenHeight ,mSwipeStartThreshold 这是三个值都是0,导致在下面函数返回SWIPE_NONE

android6.0 TV 添加自定义导航栏_第2张图片

添加如下一段代码功能就正常手势滑开了

    public SystemGesturesPointerEventListener(Context context, Callbacks callbacks) {
       ..................
		WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); 
		screenWidth = wm.getDefaultDisplay().getWidth(); 
		screenHeight = wm.getDefaultDisplay().getHeight(); 

        mSwipeStartThreshold = 20;//checkNull("context", context).getResources()
................

这样改完后,还有个问题:导航栏滑出来的时候,上面的部分是缩上去的,而不是导航栏重叠在原画面上面。如果哪位高人有解决办法,分享一下,万分感谢
 

你可能感兴趣的:(android6.0 TV 添加自定义导航栏)