Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829
前言:上篇中,《Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版)》对应的源码解析见《TV Metro界面(仿泰捷视频TV版)源码解析》一文,链接:http://blog.csdn.net/hejjunlin/article/details/52822499,github对应地址:https://github.com/hejunlin2013/TVSample,截至到当前发稿,已突破200star,如果喜欢的话,可以star,也表示下支持,今天主要总结下TV开发中有焦点问题。
在TV开发中没有以前我们phone端的dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent 事件来分发,而需要使用dispatchKeyEvent、onKeyDown、onKeyLisenter 等事件来分发处理焦点事件传递,而且TV端焦点没有什么好办法可以全局控制,需要我们自己来想办法规定焦点走向,可以参考我的View焦点总结《Android View框架总结(二)View焦点》,本篇做应用场景补充说明及遇到有坑,看下Agenda:
- 采用Android自带的直接控制焦点上下左右
- 采用setOnFocusChangeListener控制焦点
- adb按键派发控制焦点
- 遇到的坑-遥控器按键失灵案列
Android TV 开发与一般Android开发最大的区别在于焦点控制 , 用户在使用Android TV设备主要是通过遥控器操作app。焦点就是让用户知道的直接交互行为。 然而一些app,依据系统对focus的判断,会出现的状况: 上下导航时,不是想要的结果. 边缘移动时,会出现焦点丢失的状况. 有时想直接定位到某个位置上.
android提供了一些焦点相关的属性,在现有的框架层下通过设置View的属性来获得焦点
下面列出三种方法处理焦点问题
一、采用Android自带的直接控制焦点上下左右的方法
采用Android自带的直接控制焦点上下左右的方法
因此在进行布局时有必须要通过view.setId(…)指定view的特定ID,然后通过view.setNextLeftView(…)等四个方法控制该view的上下左右移动后所到达的view。然而这种方法只适用于前提就设置好ID的场景,不适合动态布局的场景。
看如下一段布局:
rg_a1,rg_a2,rg_a3,rg_a4实际业务中会写明其含义,而不是a1,a2之类,这里只是为介绍,这个自定义的MyCustomButton,按遥控器左键时,将找id为rg_a1的view,焦点跳过去,按遥控器右键时,将找id为rg_a2的view,焦点跳过去,按遥控器下键时,将找id为rg_a3的view,焦点跳过去,按遥控器上键时,将找id为rg_a5的view,焦点跳过去。
二、采用setOnFocusChangeListener控制焦点
看如下一段代码:
当OnFocusChangeListener时,就是从一个焦点跳到另一个view上的变化过程。
三、adb按键派发控制焦点
按键的派发须了解一此KeyCode,下面是平时用到的主要的一些方向键:
在按键过程中 按下和松开的Action主要是ACTION_DOWN、ACTION_UP事件分发和处理是在ACTION_DOWN中处理
当设置View.setFocusable(true); 改变控件是否可以获得焦点,然而同时会触发 setOnFocusChangeListener事件
在adb中,可以通过注入的方式模拟按键,如 adb shell input keyevent 3 给示模拟Home键
以下是的KEYCODE供参考:
KEYCODE_UNKNOWN=0; KEYCODE_SOFT_LEFT=1; KEYCODE_SOFT_RIGHT=2; KEYCODE_HOME=3; KEYCODE_BACK=4; KEYCODE_CALL=5; KEYCODE_ENDCALL=6; KEYCODE_0=7; KEYCODE_1=8; KEYCODE_2=9; KEYCODE_3=10; KEYCODE_4=11; KEYCODE_5=12; KEYCODE_6=13; KEYCODE_7=14; KEYCODE_8=15; KEYCODE_9=16; KEYCODE_STAR=17; KEYCODE_POUND=18; KEYCODE_DPAD_UP=19; KEYCODE_DPAD_DOWN=20; KEYCODE_DPAD_LEFT=21; KEYCODE_DPAD_RIGHT=22; KEYCODE_DPAD_CENTER=23; KEYCODE_VOLUME_UP=24; KEYCODE_VOLUME_DOWN=25; KEYCODE_POWER=26; KEYCODE_CAMERA=27; KEYCODE_CLEAR=28; KEYCODE_A=29; KEYCODE_B=30; KEYCODE_C=31; KEYCODE_D=32; KEYCODE_E=33; KEYCODE_F=34; KEYCODE_G=35; KEYCODE_H=36; KEYCODE_I=37; KEYCODE_J=38; KEYCODE_K=39; KEYCODE_L=40; KEYCODE_M=41; KEYCODE_N=42; KEYCODE_O=43; KEYCODE_P=44; KEYCODE_Q=45; KEYCODE_R=46; KEYCODE_S=47; KEYCODE_T=48; KEYCODE_U=49; KEYCODE_V=50; KEYCODE_W=51; KEYCODE_X=52; KEYCODE_Y=53; KEYCODE_Z=54; KEYCODE_COMMA=55; KEYCODE_PERIOD=56; KEYCODE_ALT_LEFT=57; KEYCODE_ALT_RIGHT=58; KEYCODE_SHIFT_LEFT=59; KEYCODE_SHIFT_RIGHT=60; KEYCODE_TAB=61; KEYCODE_SPACE=62; KEYCODE_SYM=63; KEYCODE_EXPLORER=64; KEYCODE_ENVELOPE=65; KEYCODE_ENTER=66; KEYCODE_DEL=67; KEYCODE_GRAVE=68; KEYCODE_MINUS=69; KEYCODE_EQUALS=70; KEYCODE_LEFT_BRACKET=71; KEYCODE_RIGHT_BRACKET=72; KEYCODE_BACKSLASH=73; KEYCODE_SEMICOLON=74; KEYCODE_APOSTROPHE=75; KEYCODE_SLASH=76; KEYCODE_AT=77; KEYCODE_NUM=78; KEYCODE_HEADSETHOOK=79; KEYCODE_FOCUS=80;//*Camera*focus KEYCODE_PLUS=81; KEYCODE_MENU=82; KEYCODE_NOTIFICATION=83; KEYCODE_SEARCH=84; KEYCODE_MEDIA_PLAY_PAUSE=85; KEYCODE_MEDIA_STOP=86; KEYCODE_MEDIA_NEXT=87; KEYCODE_MEDIA_PREVIOUS=88; KEYCODE_MEDIA_REWIND=89; KEYCODE_MEDIA_FAST_FORWARD=90; KEYCODE_MUTE=91;
-
问题描述:播放中出现屏保,从屏保回到某页面后,遥控器失灵。从某页进入全屏播放,暂停,等小米的屏保出来后将屏保消失,返回到某页面继续播放。此时遥控器方向键、确定键均无响应。Home键、电源键有响应。菜单键有响应。
分析:没有响应,按键被拦截,查了下当时改动的代码时,对按键并未做特殊拦截…. 对比之前的版本,没有这个问题。确认问题出现在浮层…从log中看,onWindowFocusChanged,在从h5界面/屏保界面回到某页面,没有被调用。
说明从window到activity这层,按键就被吃掉了。
-
接着分析:整个BaseActivity,没有接收到Action_Down事件
Log中打印的“Dropping event due to no window focus”,思路又断了。
继续做对比,发现show出浮层时,没有任何异常,但是只要show时,焦点移动,就能复现按键不响应。最后就定位到一个自定义控件上
- 再接着分析:这个控件1600多行代码,最初一直在找之前版本改动的地方区别,之前版本主要是做一些对这个控件的定制化,其他的先不考虑,排除法,找和event相关的方法。dispatchKeyEvent没有任何异常,又没有思路了,既然是系统级别的传递过程中就被吃了,会不会和view相关,因为只要焦点移动,就失灵,焦点移动伴随着,有一个popupwindow弹出,最终定位在onAttachWindow,好像也没有做什么特殊的事,用了一个getHandler,起初我以为是个自己写的方法,追点进去getHandler一看,是View的
- 问题修复:
总结:用View的Handler以前是为处理popupwindow时,popupwindow通过post的方式去show,但是如果此时activity ondestory则会导致出错,所以加了onDetachWindow和onAttachWindow,原因主要是在onDetachWindow时,mHandler.removeCallbacksAndMessages(null);这句话导致,它相当于是把window发给View这层message给移除了。最后修改只移除它对应的的runnable,问题修复。
第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。
如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版)
原文: Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版) 版权声明:我已委托“维权骑士”(rightknights.com)为我的文章进行维权行动.转载务必转载所有,且须注明出处。否则保留追究法律责任 https://blog.csdn.net/hejjunlin/article/details/52809433 前言:上篇是介绍构建TV app前要知道的一些事儿,开发Android TV和手机本质上没有太大的区别,屏大,焦点处理,按键处理,是有别于有手机和Pad的实质区别。今天来介绍TV中Metro UI风格,并结合实例说明。 Android TV发展离不开Metro UI,先看最新的泰捷TV的会员区效果,属于典型的Metro风格,如下: 什么是Metro UI: Metro的设计意念来源于交通局巴士站站牌机场和地铁的指示牌给了微软设计团队灵感,设计团队说Metro是来源于美国华盛顿州金县都会交通局(King County Metro)的标识设计,其风格大量采用大字体,能吸引受众之注意力。微软认为Metro设计[2] 主题应该是:“光滑、快、现代”。...
- 下一篇
Android TV开发总结(五)TV上屏幕适配总结
原文: Android TV开发总结(五)TV上屏幕适配总结 版权声明:我已委托“维权骑士”(rightknights.com)为我的文章进行维权行动.转载务必转载所有,且须注明出处。否则保留追究法律责任 https://blog.csdn.net/hejjunlin/article/details/52886107 前言:前面几篇总结一些TV上的小Sample,开源到GitHub: https://github.com/hejunlin2013/TVSample , 点击链接,可以持续关注。今天总结下TV上屏幕适配.: 看下Agenda: 一、屏幕适配的一些背景知识 二、TV屏幕适配怎么适配?有哪些规则? 三、多屏幕适配,android读取res/drawable优先级是什么? 四、屏幕分辨率及density 、densityDpi代码 一、屏幕适配的一些背景知识 介绍几个在Android屏幕适配上非常重要的名词: 1 什么是屏幕尺寸、屏幕分辨率、屏幕像素密度? 屏幕尺寸是指屏幕对角线的长度。单位是英寸,1英寸=2.54厘米; 屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker安装Oracle12C,快速搭建Oracle学习环境
- MySQL8.0.19开启GTID主从同步CentOS8
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2配置默认Tomcat设置,开启更多高级功能