Android原生Switch禁止滑动实现

前言 

搜遍全网,没有找到对原生控件实现禁止滑动的,全都是自定义view实现。然后自己找到了一个解决方式,可以不重写Switch控件,只用style就能实现。

这边先说一下有滑动效果会产生的问题:

在注册了监听事件setOnCheckedChangeListener之后,通过代码去setCheck它也会进去change事件里面,但实际上我们不希望这个事件的发生,我们只想纯UI上的变化。

网上有两种解决思路:

第一种,也是比较笨的方法,setCheck前把change监听设置为null,setCheck完再监听回来:

view.setOnCheckedChangeListener(null);
view.setChecked(isChcek);
view.setOnCheckedChangeListener(listener);

这种方法很明显是无奈之举, 虽然说可以封装一下,但是每次都要传这个listener,而我这个listener是一个匿名内部类你还要修改成变量。

第二种,也是网上目前最佳的解决方案,change事件里面判断是否是用户按下的,如果不是那就认为是代码setChcek的,则不往下执行:

switchView.setOnCheckedChangeListener((compoundButton, isCheck) -> {
     if (!compoundButton.isPressed()) {
           return;
     }
     //todo
});

这种方法看似很完美,但是有一个致命的bug:如果你在滑动块那里快速滑动过去,触发了change事件,但是这个isPressed却是false!!!这你敢信,好家伙,趁这个事件反应过来之前手就抬起来了,这样原本应该执行change事件的却被你return掉了,实际开关和显示开关就会不一致。

解决:

为了解决这个问题我百度了好久,都没有找到有效的解决方案,想过重写Switch,自定义view,换checkBox控件等等,但是我这里的项目界面上很多个Switch,全部监听都是用的第二种方法。要换一个控件的话不仅要改layout还要改代码上的控件,就要改大量代码,很麻烦。

我想最可行的就是有一个方法可以屏蔽掉这个滑动块的滑动效果,只要不给你滑动,你的isPressed就只能乖乖代表用户点击。

原生Switch也没有提供禁止滑动只能点击的方法,我们的解决思路是把原来的滑动块(包括滑动轨道)隐藏掉,然后给控件设置一个居右显示的图片来代表这个选中状态。因为我这边全部Switch都是用的一个style,所以只要修改这个style就可以了,不用动layout和代码:

<item name="android:thumb">@null</item>
<item name="android:track">@null</item>
<item name="android:background">@null</item>
<item name="android:drawableEnd">@drawable/selector_check_switch</item>

滑块设置为空,滑动轨道设置为空,这样就不显示原状态了,然后background是你点击的时候会有一个白色扩散的点击效果,而且滑动和轨道都设置null了之后它会显示在中间,所以这里设置为null让它不显示,或者你也可以设置成你项目里面的Switch的背景。

图片原来是用的shape写的xml资源文件,两种状态的图片可以叫UI给你切图,也可以用代码实现,用一个重叠资源的layer-list:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- 滑块的shape -->
    <item> 
        <shape android:shape="rectangle">
            <!-- 把原来滑块的shape放这里 -->
        </shape>
    </item>

    <!-- 轨道的shape -->
    <item android:left="@dimen/switch_margin">
        <shape android:shape="rectangle">
            <!-- 把原来轨道的shape放这里 -->
        </shape>
    </item>
</layer-list>

定义一个开的,一个关的,再放到需要引用的selector文件里面:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:drawable="@drawable/shape_switch_open" />
    <item android:state_checked="false" android:drawable="@drawable/shape_switch_close" />
</selector>

搞定,看效果吧,和原来的一毛一样,只是不能滑动了。

猜你喜欢

转载自blog.csdn.net/qq_35584878/article/details/121141920