遥控器场景下,recyclerview焦点丢失问题

背景说明

一个Android TV项目,显示一个wifi列表,在监听到wifi状态改变时需要刷新该列表(也就是说该recyclerview可能随时需要刷新数据),实践过程中发现,如果当前控制遥控器焦点滑动停留在wifi列表的某一项,这时候外部条件导致列表自动刷新,会导致我遥控器的焦点丢失(自动跑到我的recyclerview外面的其他可以获取焦点的view上了)

如何解决

核心思路:记住刷新前的焦点位置,刷新列表时将焦点还原

这里有一点细节需要注意,我们要还原前需要判断当前的recyclerview是否包含焦点,如果用户根本没有将焦点滑动到该recyclerview(我们的页面上存在其它view,用户当前并没有将焦点移动到该recyclerview的某个条目),那么我们就不需要将焦点还原
如何记住呢,这里我使用的BRVAH 4.0版本实现adapter,原生adapter是一样的处理

class WifiListAdapter: BaseQuickAdapter<CMWiFiInfo, WifiListAdapter.VH>() {
    var focusPosition = -1
    class VH(parent: ViewGroup, val binding: AdapterWifiListBinding = AdapterWifiListBinding.inflate(
        LayoutInflater.from(parent.context))): RecyclerView.ViewHolder(binding.root)

    override fun onBindViewHolder(holder: VH, position: Int, item: CMWiFiInfo?) {
        ......//其它业务处理
        holder.itemView.setOnFocusChangeListener { v, hasFocus ->
            if(hasFocus){//在这里我们记录最后获取焦点的位置
                focusPosition = holder.absoluteAdapterPosition
            }
        }
    }

    override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
        return VH(parent)
    }

那么在我们需要刷新列表的时候,将焦点还原需要如何处理呢

    fun updateWifiList(){
        val containsFocus = binding.rvWifi.hasFocus() //这里是判断当前recyclerview是否包含焦点,这个判断一定要做,原因在前面已经说过
        mWifiListAdapter.submitList(customWifiManager.getList().filter { !TextUtils.isEmpty(it.SSID) }.sortedBy { it.level }.reversed())//这里主要是排序后刷新列表数据
        if(containsFocus){
//            binding.rvWifi.findViewHolderForAdapterPosition(lastfocusItemPosition)?.itemView?.requestFocus()
            binding.rvWifi.post {//这里为什么要用view.post呢?因为我们应该保证view绘制完成后再进行焦点控制,否则可能导致列表未绘制完成找不到对应的position及position对应的view,造成异常crash
                binding.rvWifi.scrollToPosition(mWifiListAdapter.focusPosition)
                binding.rvWifi.findViewHolderForAdapterPosition(mWifiListAdapter.focusPosition)?.itemView?.requestFocus()//这里就是将焦点位置还原

            }
        }
    }

上面讨论的实现逻辑我已经在Android12版本的设备上验证正常,需要注意的是这里的逻辑是按照位置还原焦点的,我们上一次刷新列表的第n条可能对应wifi名称是AAA,那么在下一次刷新列表时,第n条可能对应的是AAA也可能是BBB,所以不能保证焦点一直维持在原来数据(AAA)的地方。当然,如果你不想按照位置还原,只想按照数据的位置还原(比如不论怎么刷新,我就是想回到用户上次焦点选中的AAA),我们也可以按照这种上面思路扩展,这里先不讨论,如果有需要再拓展,继续牛马生活地赶项目了

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容