大概二年前,曾经遇到一个问题,使用SwitchPreference的子类时,Switch的点击动画居然没了,原本点击后SwitchPreference有一个过渡的动画,使用子类就变成了很生硬的直接选中的状态,但是奇怪的是子类没有任何修改!!当时还记得因为这个原因被迫选择了其他的方案。。
结果现在在修改一个开源项目的时候又遇到了,于是阅读了SwitchPreference及其父类的源码,居然发现了解决办法。
首先SwitchPreference是一个系统组件
SwitchPrerenece -> TwoStatePreference -> Preference
SwitchPrerenece 和 TwoStatePreference 代码较少,大部分代码都集中在Preference里
在Preference的构造方法的最后的地方有这么一段代码
if (!getClass().getName().startsWith("android.preference")
&& !getClass().getName().startsWith("com.android")) {
// For non-framework subclasses, assume the worst and don't cache views.
mCanRecycleLayout = false;
}
居然判断了类的包名,我们在继承SwitchPreference的时候除了包名没有作任何的修改,所以我就尝试把SwitchPreference的子类放在android.preference包下
package android.preference;
import android.content.Context;
import android.util.AttributeSet;
import sp.phone.bean.PreferenceConstant;
public class SwitchCompatPreference extends SwitchPreference {
public SwitchCompatPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwitchCompatPreference(Context context) {
super(context);
}
}
居然奇迹般的出现了动画效果, 搜索了mCanRecycleLayout在Preference中使用的地方
public void setLayoutResource(@LayoutRes int layoutResId) {
if (layoutResId != mLayoutResId) {
// Layout changed
mCanRecycleLayout = false;
}
mLayoutResId = layoutResId;
}
public void setWidgetLayoutResource(@LayoutRes int widgetLayoutResId) {
if (widgetLayoutResId != mWidgetLayoutResId) {
// Layout changed
mCanRecycleLayout = false;
}
mWidgetLayoutResId = widgetLayoutResId;
}
boolean canRecycleLayout() {
return mCanRecycleLayout;
}
也就是说当我们继承Preference或者在java代码里设置了layout或者WidgetLayout的时候,这个变量就被置为false,就会丢失动画。