前言
Switch 是 Android 自带的开关控件,和 CheckBox ,RadioButton 都继承自同一个父亲(CompoundButton),这几天因为业务需要,使用了 Switch ,一开始以为和 CheckBox 这些控件一样简单操控,结果碰了一脸灰,以下一一道述。
踩坑
我用 Switch 是打算对用户的某一个状态进行控制,并且需要将状态发送至后台接口进行保存,所以在用户对 Switch 进行开关调整后直接调取后台接口保存。问题来了,如果用户是在断网后对 Switch 进行操作,又或者连接后台超时的情况下,这个用户操作的状态并没有发送至后台,这时候是需要将 Switch 重置回来的(如用户打开 Switch ,那么请求后台失败后得将 Switch 关上),代码奉上(已经获取到 Switch 实例)
// Lambda 表达式,你有我有全都有
switch.setOnCheckedChangeListener((buttonView, isChecked) -> {
ServerManager.getInstance()
.setStatus(int flag) // 0 为关闭,1 为开启
.subscribe(new ObserverImpl<Response>() {
@Override
public void onNext(Response response) {
if (response.status != 200) {
// 请求失败,重置 Switch
switch.setChecked(flag == 0 ?true : false); // 假设用户是打开,这里就得关上,反之亦然
}
// do something
}
@Override
public void onError(Throwable e) {
// 请求失败,重置 Switch
switch.setChecked(flag == 0 ? true : false); // 假设用户是打开,这里就得关上,反之亦然
}
});
})
一开始这样写没发现什么问题,然后开始调试,网络正常的情况下没什么问题,但当我将 WIFI 和流量关了之后,再点击 Switch ,妈蛋这个 Switch 一直在跳来跳去,打开关闭打开关闭......到这里突然明白了,因为给 Switch 设置的监听器是监听 Switch 的开关状态,只要调用了 setChecked() 就肯定会回调到我们监听器里的回调方法,所以在这里面重置 Switch 状态自然就出问题了。
找办法
我尝试过用 Switch 进行 setOnClickListener() ,是可以解决这个重复 setChecked() 的问题,但是有一点毛病,如果你不是对其进行点击,而是拖动来开关的话是无法触发点击事件的。通过网上查找的方法,有说在 setOnCheckedChangeListener() 的回调方法里对用户行为进行判断,如果非用户点击行为就直接 return ,来看一下代码
switch.setOncheckedChangeListener((buttonView, isChecked) -> {
if (!buttonView.isPressed()) return;
// do something
})
这样的话,如果不是用户去操控这个 Switch 的话,这段代码就不会执行了......但是,这段代码也有个问题,跟上面的一样,如果用户是拖动的话,默认会被认定为非点击,所以走到 if (!buttonView.isPressed()) 的时候自然就 return 了。
解决办法
其实就是上面第一个办法,setOnClickListener() ,但不是对 Switch 设置监听器(别打我啊,曲线救国也是可以的嘛),在布局文件中对 Switch
套上一层布局,调用 switch.setClickable(false) 禁止 Switch 响应点击事件(连滑动也不行), 再对 Switch 的父布局(即套上的这个壳)设置点击监听 switchParent.setOnClickListener() ,这样的话问题就解决了,有一个缺点,就是 Swtich 没办法再进行滑动了,毕竟设置了 setCLickable(false) ,但是照样能响应用户点击,因为套了个壳,并且如果你将手指按在 Switch 的壳上(或者 Switch)的话,你会发现 Switch 会有 Selector 状态出现(即 pressed 状态),这样用户照样能知道这个 Switch 是能够响应点击的。这种情况下,即使用户网络不好,操控状态发不出去的情况下也会对 Switch 状态重置,并且也不会出现 Switch 左右跳舞,因为压根就没调用 setOnCheckedChangeListener() 设置监听器,问题解决。
END