AndroidTV开发5——解决Recyclerview快速移动时焦点错乱问题

       我们知道在TV项目中,最主要的就是焦点事件的处理,今天要说的是当使用多个Recyclerview时焦点错乱问题.操作是当我们横向快速移动或者连续操作就会发生焦点主动跑得下一个或下一排控件上面.

我们看看焦点乱飞的截图:

从上图中可以看出,快速移动键盘到右边最后item时自动跑到下边的列表去了,然后使用键盘快速移动第二排的item时焦点自动跑到第一排的左边第一个,这就是 焦点乱跑的现象,这里我只是写了一个简单例子,复现焦点乱跑问题,所以用2个Recyclerview,实际项目肯定用一个更好,不要嵌套,这里不要纠结,本篇主要是解决焦点乱跑问题。

分析:

1.产生焦点错乱的原因: RecyclerView在长按遥控器的情况下会导致Item的焦点丢失或者说是飞到别的控件上。主要是因为RecyclerView设置适配器,将数据全部填充进去之后,并不会将所有的item的view创建出来,只会创建出显示和需要的item的View,没有显示的Item的View很可能没有被创建。所以在快速移动的时候,RecyclerView并没有创建那个应该获取焦点的View,所以导致焦点飞到其他可承载焦点的View上去了。

2.解决焦点错乱到处瞎跑的方法如下:

自定义RecyclerView,拦截dispatchkeyEvent事件,根据遥控器按钮操作来获取焦点

AndroidTV开发5——解决Recyclerview快速移动时焦点错乱问题_第1张图片

package com.example.tvrecyclerview.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.View;

import androidx.recyclerview.widget.RecyclerView;

/**
 * @author: njb
 * @Date: 2020/6/30 17:57
 * @desc: 解决Recyclerview焦点乱跑问题
 */
public class FocusRecyclerView extends RecyclerView {
    public FocusRecyclerView(Context context) {
        super(context);
    }

    public FocusRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            int keyCode = event.getKeyCode();
            // 这里只考虑水平移动的情况(垂直移动相同的解决方案)
            if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                View focusedView = getFocusedChild();  // 获取当前获得焦点的view
                View nextFocusView;
                try {
                    if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {
                        // 通过findNextFocus获取下一个需要得到焦点的view
                        nextFocusView = FocusFinder.getInstance().findNextFocus(this, focusedView, View.FOCUS_LEFT);
                    } else {
                        // 通过findNextFocus获取下一个需要得到焦点的view
                        nextFocusView = FocusFinder.getInstance().findNextFocus(this, focusedView, View.FOCUS_RIGHT);
                    }
                } catch (Exception e) {
                    nextFocusView = null;
                }
                // 如果获取失败(也就是说需要交给系统来处理焦点, 消耗掉事件,不让系统处理, 并让先前获取焦点的view获取焦点)
                if (nextFocusView == null) {
                    focusedView.requestFocus();
                    return true;
                }
            }
        }
        return super.dispatchKeyEvent(event);
    }

}

这里我放上使用自定义recyclerview的截图和效果图:

从下图中可以看到,不管是第一排还是第二排当快速移动键盘时都没有出现刚开始焦点乱跑的现象。

AndroidTV开发5——解决Recyclerview快速移动时焦点错乱问题_第2张图片

3.总结:遇到问题不要怕,要学会分析问题,寻找原因,然后找出解决方案,可以查找资料,和同事相互讨论,看前辈或者同事有没有遇到类似的,虚心向他们请教,不要害怕,大神也是从菜鸟一步步走过来的,最后希望本文对小伙伴们有用.小伙伴们可以自行尝试本文的例子,写两个列表,后面还会总结有单选框、上一步、下一步等等多个按钮时,焦点如何寻找及处理.如小伙伴们有更好地的解决方案,可以给我留言,一起学习和成长。

完整的项目地址如下:https://gitee.com/jackning_admin/TvRecyclerView

 

你可能感兴趣的:(AndroidTV开发)