我遇到了同样的问题,我设法通过一些最小的反射解决了它。
用法:
要在没有动画的情况下更改开关状态,请调用 setChecked(boolean checked, boolean animate) 方法,并将 animate 参数设置为 false。如果在调用此方法的那一刻开关已经开始动画,则动画将停止并且开关跳转到所需的位置。
SwitchCompatFix.java
import android.content.Context;
import android.support.v7.widget.SwitchCompat;
import android.util.AttributeSet;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Work around for: http://stackoverflow.com/questions/27139262/change-switch-state-without-animation
* Possible fix for bug 101107: https://code.google.com/p/android/issues/detail?id=101107
*
* Version 0.2
* @author Rolf Smit
*/
public class SwitchCompatFix extends SwitchCompat {
public SwitchCompatFix(Context context) {
super(context);
initHack();
}
public SwitchCompatFix(Context context, AttributeSet attrs) {
super(context, attrs);
initHack();
}
public SwitchCompatFix(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initHack();
}
private Method methodCancelPositionAnimator = null;
private Method methodSetThumbPosition = null;
private void initHack(){
try {
methodCancelPositionAnimator = SwitchCompat.class.getDeclaredMethod("cancelPositionAnimator");
methodSetThumbPosition = SwitchCompat.class.getDeclaredMethod("setThumbPosition", float.class);
methodCancelPositionAnimator.setAccessible(true);
methodSetThumbPosition.setAccessible(true);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public void setChecked(boolean checked, boolean animate){
// Java does not support super.super.xxx calls, a call to the SwitchCompat default setChecked method is needed.
super.setChecked(checked);
if(!animate) {
// See original SwitchCompat source:
// Calling the super method may result in setChecked() getting called
// recursively with a different value, so load the REAL value...
checked = isChecked();
// Cancel any running animations (started by super.setChecked()) and immediately move the thumb to the new position
try {
if(methodCancelPositionAnimator != null && methodSetThumbPosition != null) {
methodCancelPositionAnimator.invoke(this);
methodSetThumbPosition.invoke(this, checked ? 1 : 0);
}
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
proguard 用户注意事项:
由于此方法使用反射,因此可能需要额外的 proguard 规则(如果尚不存在)。
-keep class android.support.v7.widget.SwitchCompat {
private void cancelPositionAnimator();
private void setThumbPosition(float);
}
当您使用以下 proguard 规则之一(或类似规则)时,不需要此附加规则:
-keep class android.support.v7.widget.** { *; }
-keep class android.support.v7.** { *; }