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 这篇文章,屏蔽掉一行
再修改 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
添加如下一段代码功能就正常手势滑开了
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()
................
这样改完后,还有个问题:导航栏滑出来的时候,上面的部分是缩上去的,而不是导航栏重叠在原画面上面。如果哪位高人有解决办法,分享一下,万分感谢