Android 多点触控 RadioGroup + Fragment 实现的底部Tab 能防止用户同时点击多个button而只响应一个有效事件吗?

Android底部导航栏(底部Tab)是一个Android程序员入门必须会实现的一个功能点,在Material Design(基于Android 5.0 API level 21)设计出来之前大家实现底部Tab通常会用FragmentTabHost或RadioGroup方式。而在有了
Android Support Library (com.android.support:design:xx.x.x)
后就可以使用官方 提供的TabLayout 或 BottomNavigationView 控件了。

当然这篇文章不是去讲上面提到的4种方式怎么去实现的,而是分析一下早期使用RadioGroup方式实现时的一些疑问,证实一下的自己的判断。
当时采用 RadioGroup + RadioButton组合使用实现单选功能,就想到了一个case:当用户同时点击多个Tab的时候,RadioGroup控件的OnCheckedChangeListener监听事件会不会响应多次,当时的我只是想当然地认为官方推出的这种组合应该考虑到了这个case了吧,会做处理地只会响应一次事件,自己也没去加Log验证了,就这样放任过去了……
以至于后面在再次实现底部Tab的时候, 当内心有想法采用自定义View实现Tab的(因为Icon可以高度定制),但是一想到已有成熟轮子了自己也就不去费时间弄了。

做了这么多年后,心态也会逐步发生改变,从知其然知其然知其所以然再到知其所以然知其所必然
为了验证问题,就简单做了下实验:

一个水平的线性布局包含4TextView控件,分别注册了点击事件itemClick
<LinearLayout
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:orientation="horizontal">

   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:gravity="center"
       android:onClick="itemClick"
       android:padding="10dp"
       android:text="测试1" />
   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginLeft="40dp"
       android:gravity="center"
       android:onClick="itemClick"
       android:padding="10dp"
       android:text="测试2" />
   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginLeft="40dp"
       android:layout_marginRight="40dp"
       android:gravity="center"
       android:onClick="itemClick"
       android:padding="10dp"
       android:text="测试3" />
   <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:gravity="center"
       android:onClick="itemClick"
       android:padding="10dp"
       android:text="测试4" />
</LinearLayout>

public void itemClick(View view){
        for(int i=0;i<200;i++){
           LogUtils.loge("itemClick",i+"--"+((TextView)view).getText().toString());
        }
        LogUtils.loge("itemClick结束-",((TextView)view).getText().toString());
    }

大家觉得在我们用手同时点击2个TextView控件的时候,点击事件的回调是同时进行还是先后执行呢?
Touch事件是同时接收到的,但我们再先想一下点击事件的回调是触发在哪个线程呢?。没错事件的回调是UI主线程,所以同时点击2个控件虽然都会有响应,但是点击事件触发是存在先后的,为了证明此点特意加了一个for循环延时,日志显示当同时点击2个控件时,Onclick事件的回调的确是存在先后的。
不过虽然是先后执行,但是也需要改进的,因为这属于多回调了一次事件是属于浪费,而浪费是可耻的哈。

后面也把log加在了RadioGroup控件的OnCheckedChangeListener监听事件上,发现竟然也先后执行了多次,后面去看了下源码,发现也是没做处理跟我们写自定义Tab是差不多的逻辑控制。

那么说到这里该怎么简单快速解决呢?那就是利用Android本身的多点触控功能:
只要在xml文件中的父容器加入这样一行代码即可:
android:splitMotionEvents=”false”或者动态代码.setMotionEventSplittingEnabled()
如在上面的LinearLayout中加入这行话,表示每一次只能点击LinearLayout其中的一个元素,点击了其他的元素是无效的。

如果一次性应用到Application、Activity的话,可以通过自定义主题的方式来关掉多点触摸功能
在windows中禁止split touch events:
<style name="NoSplitMotionEvents" parent="Theme.xxx">
     <item name="android:windowEnableSplitTouch">false</item>
     <item name="android:splitMotionEvents">false</item>
         ...      
</style>

所以咱们也只需在RadioGroup的xml上添加android:splitMotionEvents=”false”即可解决问题

猜你喜欢

转载自blog.csdn.net/u012982629/article/details/80879411
今日推荐