TV按键拦截问题

Bug描述

对象:当前View、下一级View、遥控板按键、密码输入框。
操作:在当前View,使用按遥控键OK进入密码输入框,正确输入密码,点击OK后立马按下键(此时下一级View还未加载出来)。
结果:此时当前View响应下键(下移一项),焦点在下一级View(此时下一级View已未加载出来)。
频率:30%
原因:下一级View布局、渲染等需要时间,所以此时按遥控键,下一级View并不能接收到按键事件,于是当前View接收按键并消费了。
其实,严格来说,这是Android的按键分发问题。本应该分发到下一级,却误分发给了当前View。
解决:有如下五种方式可尝试(ps:我是用第五种方式解决问题的)

解决方法一

方式:优化下一级View的加载

既然问题出在下一级View未显示,而此时又来了按键事件(ps:按键响应和加载View,它们是异步进行的),导致下一级View无法响应按键事件。那么首先想到的就是:缩短下一级View的加载时间,减少中间的空档期。

评价:这种方式,得看自己View加载的耗时以及渲染优化等。

解决方法二

方式:设置应用全局变量(默认false)

1、密码输入框正确输入密码时,会加载下一级View,此时设置全局变量为true,当下一级View加载好并获得焦点时将全局变量设为false。

2、重写当前View的dispatchKeyEvent(),在首行判断该全局变量如果为true,就返回true(不拦截事件,继续向下传递);全局变量如果为false,就返回false(表示当前View已消费该事件,不再向下传递)。

评价:会丢失按键响应(因为当前View未拦截,下一级View还未加载完成);如何判断下一级View什么时候加载好以及获得焦点的时间,这是个问题。

解决方法三

方式:预加载下一级View

当前View加载密码输入框时,同时加载下一级View。

评价:这种方式需要将下一级View分解成加载、显示和释放等。(1)下一级View的显示速度快了些,但是依旧存在当前View接收按键并消费了的情况,只是Bug发生频率有所下降,是一种优化的可行方式。(2)如果密码输入框之后不显示下一级View,此时的预加载就得注意内存释放等问题了,小心memory leak。

解决方式四

方式:150ms内取消按键响应

因为,这是用户操作过快导致的概率性Bug,一般我们可以,在一定时间内取消用户的操作。

评价:这得视项目情况而定。

解决方式五

方式:离开当前View时就不再接收按键响应,重新回到当前View时继续接收按键响应。

这是最正常的逻辑,这正所谓:你走,我不送你;你来,即使风再大雨再大,我,都要去接你。

代码实现:只在四处添加,分别是:声明变量为false、复位false、离开当前View时设为true、dispatchKeyEvent()判断是否去消费该按键(ps:Kotlin实现)

var isEnterNextView: Boolean = false // 声明变量为false

override fun onDismissPopView(level: Int) { // 复位
        Log.d(TAG, "onDismissPopView")
        isEnterListPopView = false // 每次从下级——ListPopView返回时,会触发此回调。

SettingWidgetManager.showPasswordDialog(mContext1, object : SettingWidgetManager.PasswordDialogCallBack {
    override fun correct() {
        isEnterNextView= true // 离开当前View时设为true
        view.showPopView(baseVm.getPopViewType(), mViewLevel, this@SettingView)

override fun dispatchKeyEvent(event: KeyEvent): Boolean {
    if(isEnterNextView) return true // 如果进入了下级View,此时还能收到事件响应的话,就应抛弃该事件。

评价:Bug未出时不关注此逻辑,Bug来时漫山遍野寻找灵丹妙药。原来,初恋才是最好,陪伴才是最长情的告白。

 

发布了55 篇原创文章 · 获赞 61 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Agg_bin/article/details/100567324
今日推荐