更改切换状态没有动画

在我的Android项目中,我有一个包含SwitchCompat项目(AppCompat for Switch小部件)的ListView

当我滚动到列表中,并且MyAdapter getView(...)方法与recycled视图一起调用时,就会出现问题。 我重新定义了正确的Switch状态,但动画是可见的。

在这种情况下有一个解决方案来防止动画?

在这里输入图像描述

调用jumpDrawablesToCurrentState()将跳过动画。

我终于找到了一个解决方案,但似乎不是很干净:

 ViewGroup viewGroup = (ViewGroup) view; // the recycled view viewGroup.removeView(switch); switch.setChecked(states[index]); viewGroup.addView(switch); 

如果有更好的解决方案,请分享。

我有同样的问题,我设法解决它使用一些最低限度的思考。

用法:

要在没有动画的情况下更改开关状态,请为animate参数调用false的setChecked(boolean checked, boolean animate)方法。 如果在调用此方法时开关已经开始动画,则动画将停止,开关跳转到所需的位置。

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.** { *; } 

使用SwitchCompat和DataBinding

 @BindingAdapter({"bind:checkedState"}) public static void setCheckedState(SwitchCompat switchView, boolean checked) { int visibility = switchView.getVisibility(); switchView.setVisibility(View.INVISIBLE); switchView.setChecked(checked); switchView.setVisibility(visibility); } 

然后在xml中:

 <android.support.v7.widget.SwitchCompat android:id="@+id/my_switch" android:layout_width="wrap_content" android:layout_height="wrap_content" app:checkedState="@{my_data.checked}"/> 

如果您使用Android数据绑定,则可能会出现在列表中动画播放的问题。

为了解决这个问题,在设置数据之后运行binding.executePendingBindings()方法 – 它将刷新当前帧中组件的绑定状态,不会等待下一个组件的到来。

正如你可能已经猜到了 – 下一帧是动画

对于Kotlin开发人员:

 fun SwitchCompat.setCheckedWithoutAnimation(checked: Boolean) { val beforeVisibility = visibility visibility = View.INVISIBLE isChecked = checked visibility = beforeVisibility } 

用法:

 mySwitch.setCheckedWithoutAnimation(true)