欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android多点触控RadioGroup结合Fragment实现底部Tab

程序员文章站 2022-10-30 18:39:37
android底部导航栏(底部tab)是一个android程序员入门必须会实现的一个功能点,在material design(基于android 5.0 api level 21)设计出来之前大家实...

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可以高度定制),但是一想到已有成熟*了自己也就不去费时间弄了。

做了这么多年后,心态也会逐步发生改变,从知其然到知其然知其所以然再到知其所以然知其所必然。

为了验证问题,就简单做了下实验:

一个水平的线性布局包含4个textview控件,分别注册了点击事件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”即可解决问题