android 按键分析,Android TV开发按键与焦点深入分析(四)
8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
前面三篇都是从源码的角度分析按键事件、焦点变换的原理,作为应用层的开发者,
分析源码都是带着实际的开发困惑的,要不然谁没事做会read the fucking source code,
今天就分享一个Android TV开发中的解决的焦点移动问题。
起因
使用过奇异果TV应用的同学会发现它有焦点换行的功能,就是当一直按遥控器右键时焦点View会换行到下一行的第一个View,如下
使用体验很好,重要的是产品同学也觉得很好。
看到这个效果,我的第一直觉是给每个View设置Id,Id从左到右、从上到下增加,或者给每个View设置自增的Tag,
每次都去寻找Id + 1或者Tag +1的View,然后让它获得焦点,这不就OK了。
但这还是没有优雅的解决问题,只是把问题抛给了后台、运营,让他们一个一个的设置运营位的编号。
那有没有成本很小的解决方法呢?
getFocusedRect方法
上一篇的分析中我们知道当按键事件要转换成焦点移动时,需要在众多的View中寻找一个位置
最合适的View,然后让它获得焦点。而这个位置的依据是什么?其实就是每个View的getFocusedRect返回的Rect,
对于当前有焦点的View,用这个返回的Rect计算它搜寻的起始位置;对于没有焦点的View,用
这个Rect来表示自己当前的位置。View的这个方法的代码如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14* When a view has focus and the user navigates away from it, the next view is searched for
* starting from the rectangle filled in by this method.
*
* By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
* of the view. However, if your view maintains some idea of internal selection,
* such as a cursor, or a selected row or column, you should override this method and
* fill in a more specific rectangle.
*
* @param r The rectangle to fill in, in this view's coordinates.
*/
public void (Rect r){
getDrawingRect(r);
}
实际上默认返回的就是View的绘制区域,但注释也说了可以根据实际的需要自己修改,那我就有一些想法了:可以根据View在不同的位置返回不同的Rect。
原理与实现
1.原理对于有焦点的View,如果它没靠近屏幕的边缘,这个方法返回实际的绘制区域
对于有焦点的View,如果它靠近屏幕的右边缘,将这个Rect移动到下一行的左侧屏幕的左外侧,左边缘的View同理
对于没有焦点的View,这个方法返回实际的绘制区域
这样当在右边缘的View上按右键时,实际上它的搜寻的起始位置在下一行的左外侧,位置最合适的View就是下一行第一个View,这样就可以花很小的代价解决这焦点换行的问题。
原理图如下:
当View在屏幕右边缘时,将Focus Rect的top设置为自己的botom的位置、Rect的right设置为0,
实际的搜索起始Rect是黑色虚线的Rect(原理可看上篇的分析),这样最合适的获得焦点的View就是第二行的第一个View,
达到了换行的目的
2.实现
重写View的getFocusedRect方法如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34public final void (Rect r){
//如果有焦点
if (isFocused()) {
//获得根View的绘制区域
rootView.getDrawingRect(mRootViewRect);
//获得自己的绘制区域
getDrawingRect(mTempDrawingRect);
//转换自己的绘制区域到根View的坐标系中去,方便计算FocusedRect的位置
rootView.offsetDescendantRectToMyCoords(this, mTempDrawingRect);
//判断自己是否满足换行的条件,1)按右键 2)自己在屏幕的右边缘
if ((mTempDrawingRect.right + 20) > mRootViewRect.right && currentKeyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
//重新获取自己的位置
getDrawingRect(mTempDrawingRect);
//转换根View的坐标系中去
rootView.offsetDescendantRectToMyCoords(this, mTempDrawingRect);
//将这个Rect移动到自己的下方、左侧屏幕的左外侧
mTempDrawingRect.left = 0 - getMeasuredWidth();
mTempDrawingRect.right = 0;
mTempDrawingRect.bottom = mTempDrawingRect.bottom + getMeasuredHeight();
mTempDrawingRect.top = mTempDrawingRect.top + getMeasuredHeight();
//将focus rect的坐标系还原到自己的坐标系
rootView.offsetRectIntoDescendantCoords(this, mTempDrawingRect);
r.set(mTempDrawingRect);
} else if (mTempDrawingRect.left - 20 < mRootViewRect.left && currentKeyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
//左键同理
......
} else {//没有在左右边缘或者没有按对应的左右键
super.getFocusedRect(r);
}
} else {//没有焦点
super.getFocusedRect(r);
}
}
android 按键分析,Android TV开发按键与焦点深入分析(四)相关推荐
- android listview 分析,Android中ListView用法实例分析
本文实例分析了Android中ListView用法.分享给大家供大家参考,具体如下: 通过在Layout中添加ListView Widget可以达到在页面布局具有列表效果的交互页面.在这里通过举例来说 ...
- android 图库分析,Android开发之ImageSwitcher相册功能实例分析
本文实例讲述了Android开发之ImageSwitcher相册功能.分享给大家供大家参考,具体如下: 简介: 1.ImageSwitcher是viewSwitcher的子类,所以ImageSwitc ...
- android dumpsys 分析,Android开发调试性能分析工具:dumpsys
dumpsys可以用来查看android系统运行过程中的信息状态,如CPU.内存使用.... 例1:查看dumpsys的"子命令" adbshell dumpsys | grep ...
- ios android安全性分析,Android与iOS的对比分析及Android安全技术的设计与实现
摘要: 近年来科技的发展和进步极大的推动了智能手机的飞速发展,手机功能的日益强大使人们对其依赖度显著上升.作为与人们生活密不可分通讯工具,手机安全的重要性不言而喻.现如今,随着手机网络的迅猛发展和形形 ...
- android adb 分析,android adb shell常用脚本分析课件.ppt
android adb shell常用脚本分析课件 ADB概要 Android 调试系统是一个面对客户服务系统,包括三个组成部分: 电脑上运行的客户端. 在你用于开发的机器上作为后台进程运行的服务器. ...
- android gc分析,android GC浅析
在dalvik中,GC的类型有三种: 1.GC_EXPLICIT: 应用主动调用System.gc()产生的GC事件. 2.GC_FOR_ALLOC: 3.GC_CONCURRENT: 给Java层的 ...
- android apk 分析,Android APK分析工具
1.Apktool 官网:http://ibotpeaches.github.io/Apktool/ 源码: Github地址:https://github.com/iBotPeaches/Apkto ...
- android latinime分析,Android AOSP输入法(LatinIME)大写判断分析
LatinIME源码地址:https://android.googlesource.com/platform/packages/inputmethods/LatinIME/+/android-5.1. ...
- 【Android 逆向】Android 系统文件分析 ( Android 系统 root 环境准备 | 查看 Android 根目录信息 )
文章目录 一.Android 系统 root 环境准备 二.查看 Android 根目录信息 一.Android 系统 root 环境准备 需要一部 root 过的手机 , 或者直接使用带有 root ...
最新文章
- Git合并和变基简介:它们是什么,以及如何使用它们
- 2015#183;Fool#39;s Day#183;NND
- 用批处理编译*.sln工程(转)
- 本地IDC机房数据库容灾解决方案
- python:字典,元组
- POSIX线程的同步
- PHP如何添加变量 $_SERVER
- Windbg教程-调试非托管程序的基本命令上
- 脸部螨虫和肥皂洗脸的问题
- 2017计算机软件考试试题,2017年计算机应用考试试题含答案.doc
- hadoop--MapReduce_WordCount词频统计案例
- 印象笔记支持Markdown语法
- 华为云PBX_基于华为云客服平台打造的比特百灵鸟AI管家解决方案发布
- [转帖]怎样选择(FC-SAN)光纤通道(存储)交换机
- 培训班作业---作业1:公羊母羊生小羊的问题
- 程序员离职原因的最佳回答_转行面试,高情商回答“你为什么要离职?”(建议收藏)...
- mysql rpl_MySQL rpl_semi_sync_master_timeout相关的一件BUG
- linux病毒通过U盘传播,一个通过U盘传播的病毒详细分析,近期抓的但是是09年的病毒...
- cython混淆加密
- 解决win2008 R2远程桌面授权过期的方法
热门文章
- 【春节歌曲回味 | STM32小音乐盒 】PWM+定时器驱动无源蜂鸣器(STM32 HAL库)
- 第三天打卡--非线性规划(1)
- Firefox 设置
- spring cloud ribbon源码解析(一)
- Python写得好,壁纸无烦恼!
- float表设计长度_Hash函数设计及面试题分析
- java计算机毕业设计教师职称评定系统源码+mysql数据库+系统+lw文档+部署
- 计算机丢失strom.dll,win10玩暗黑破坏神2缺少storm.dll怎么解决
- 测试网页兼容性时如何选择浏览器
- 添加两个tomcat 并能同时运行,修改