更改切换状态没有动画
在我的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)