20分钟,我们一起实现爱奇艺式焦点寻找

本文通过一个实际问题,探讨了Android中焦点处理和KeyEvent事件分发机制。小王在解决TV应用焦点查找和记忆问题时,研究了View的获取焦点过程、KeyEvent事件的分发和处理,以及焦点查找在FocusFinder中的实现。重点介绍了如何通过重写ViewGroup的方法实现自定义焦点处理,包括焦点记忆功能和左右按键的焦点上下移动。同时,文章揭示了ViewPager对焦点处理的特殊性,提供了针对性的解决方案。
摘要由CSDN通过智能技术生成

 

焦点处理是从Android手机开发到TV开发必须要经历的第一个关卡,最近从手机开发转到Tv开发的小王就遇到了这个问。

小王经过一个月的努力,XXTV版项目1.0版本终于迭代完成,本以为可以轻松过一个周末,但是版本刚发出去,客户便提出了问题。为什么我们的列表焦点不能像爱奇艺一样在最左边按左键的时候焦点向上,在最右边按右键的时候焦点向下?为什么我们的导航不具备焦点记忆的功能呢?

为了解决客户的问题小王花了一个周末的时间来学学Android对 KeyEvent事件的处理,并且通过技术笔记的方式来检验学习效果。因为输出是最好的学习方式。

KeyEvent事件总结:

 

  1. KeyEvent事件分为前后两个阶段,以当前焦点View接收到dispatchKeyEvent为分界点,前半部分为KeyEvent事件处理,后半部分为焦点查找。

  2. KeyEvent事件默认会交给当前拥有焦点的View进行处理。ViewGroup只是起到一个事件传递的作用。

  3. 只有直接或间接包含当前焦点View的ViewGroup才有机会调用到dispatchKeyEvent和focusSearch方法

  4. 只有直接或间接包含当前焦点View的ViewGroup,设置的OnKeyListener才可能有效果。

  5. 我们可以重写ViewGroup的dispatchKeyEvent方法来实现自己的KeyEvent事件拦截处理。

  6. 对于跨ViewGroup的焦点查找我们可以在addFocusable中进行处理,对于ViewGroup的内部焦点查找,在不打破原有的事件处理归则的情况下优先考虑重写focusSearch,其次才是dispatchKeyEvent。

 

什么是焦点记忆?什么是焦点内部搜索?

 

我们假设当前焦点 在C上,按键向右,D获取焦点,对于ViewGroup N 而言这个是焦点的内部搜索

我们假设当前焦点 在C上,按键向上,A获取焦点,这个是跨容器进行焦点查找,如果M的焦点自A离开,且只要ViewGroup M 只要有子View获取焦点,它一定在A上我们称ViewGroup M 具有焦点记忆功能。

那么应该如何解决客户的问题呢?小王主要面对下面的两个问题

  1. 如何记录上一次的焦点元素 ?

  2. 在什么时候介入焦点搜索的过程进行自己处理?

View的获取焦点时发生了什么

为了了解详细的过程,小王从View的requestFocus方法开始,到requestChildFocus发现了View获取焦点比较重要的信息。从当前焦点View起到 根ViewGroup的mFocused都记录了 含有焦点的ViewGroup。链式的保存了焦点信息。

ViewGroup:

@Override
public void requestChildFocus(View child, View focused) {
    if (DBG) {
        System.out.println(this + " requestChildFocus()");
    }
    if (getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) {
        return;
    }
​
    // Unfocus us, if necessary
    super.unFocus(focused);
​
    // We had a previous notion of who had focus. Clear it.
    if (mFo
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值