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

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

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

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

-    <bool name="config_showNavigationBar">false</bool>
+    <bool name="config_showNavigationBar">true</bool>

但是在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 实现自定义布局

<FrameLayout android:id="@+id/rot0" 和 <FrameLayout android:id="@+id/rot90" 代表导航栏在底部和右边垂直的布局,TV 不肯能像手机那样只有三个小图标,并且不会像手机那样翻转的,所以只在其中一个修改即可

在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 实际用的这个,所以布局里就只修改<FrameLayout android:id="@+id/rot0 即可,如果要在图标下添加文字,例子如下,把上图改为下图

<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                android:layout_width="@dimen/navigation_key_width"
                android:layout_height="match_parent"
                android:src="@drawable/ic_sysbar_back"
                android:scaleType="center"
                systemui:keyCode="3"
                systemui:keyRepeat="false"
                android:layout_weight="0"
                android:contentDescription="@string/accessibility_back"
                />
<LinearLayout
                android:layout_width="@dimen/navigation_key_width"
                android:layout_height="match_parent"
                android:orientation="vertical">
                <com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:src="@drawable/ic_sysbar_back"
                    systemui:keyCode="4"
                    android:layout_weight="2"
                    android:scaleType="fitCenter"
                    android:contentDescription="@string/accessibility_back"
                    />
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="@string/accessibility_back"
                    android:textColor="@color/navigation_bar_icon_color"
                    android:layout_weight="1"
                    android:textSize="10dp"
                    android:gravity="center"/>
            </LinearLayout>

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

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()
................

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Android 6.0自定义屏保,你可以按照以下步骤进行操作: 1. 首先,在你的应用程序中创建一个自定义屏保活动(Activity)。 2. 在该活动中,你可以使用自定义的布局文件来显示你想要的屏保内容,例如图片、文字、动画等。 3. 创建一个广播接收器(BroadcastReceiver),用于监听屏幕锁定和解锁事件。 4. 在广播接收器中,注册相应的Intent过滤器以侦听SCREEN_OFF和SCREEN_ON动作。当屏幕关闭时,你可以启动你的自定义屏保活动。当屏幕开启时,你可以结束自定义屏保活动。 5. 在AndroidManifest.xml文件中,声明你的自定义屏保活动和广播接收器。 6. 在设置中,找到“安全”或“屏幕保护程序”选项,选择你的应用程序作为默认的屏幕保护程序。 7. 现在,当设备屏幕超过一段时间无操作后,你的自定义屏保活动将会显示。 需要注意的是,Android 6.0及以上版本对屏保权限有一些限制。如果你的应用程序没有获取屏保权限,它将无法成为默认的屏保程序。要获得此权限,你需要在AndroidManifest.xml文件中添加以下代码: ``` <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> ``` 然后,需要在代码中使用以下方法请求允许忽略电池优化: ``` Intent intent = new Intent(); String packageName = getPackageName(); PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE); if (!pm.isIgnoringBatteryOptimizations(packageName)) { intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); intent.setData(Uri.parse("package:" + packageName)); startActivity(intent); } ``` 这样,你的应用程序将获得屏保权限并成为默认的屏保程序。现在,你可以根据上述步骤自定义屏保并在Android 6.0设备上使用它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值