Just for extending CheckBoxPreference or SwitchPreference on Android Lollipop, the widget (the checkbox or the switch) won't have animation anymore.
I'd like to extend SwitchPreference to force api < 21 to use SwitchCompat instead of the default one they are using (which is obviously wrong).
I am using the new AppCompatPreferenceActivity with appcompat-v7:22.1.1
but that doesn't seem to affect the switches.
The thing is that with just extending those classes, without adding any custom layout or widget resource layout, the animation is gone.
I know I can write two instances of my preference.xml (on inside values-v21) and it will work... But I'd like to know why is this happening and if somebody knows a solution without having two preference.xml.
Code example:
public class SwitchPreference extends android.preference.SwitchPreference {
public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SwitchPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public SwitchPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwitchPreference(Context context) {
super(context);
}
}
This or the same for CheckBoxPreference and then using:
<com.my.package.SwitchPreference />
Will make the animation in a Lollipop device to be gone.
--
Another thing I tried for the SwitchPreference (that I can with CheckBoxPreference) is to give a layout with the default id but @android:id/switchWidget
is not public while @android:id/checkbox
is. I also know I can use a <CheckBoxPreference />
and give a widget layout that is in fact a SwitchCompat, but I'd like to avoid that (confusing the names).
It seems I found a fix for your issue.
Extensive Explanation
In SwitchCompat, when toggling the the switch, it tests a few functions before playing the animation:
getWindowToken() != null && ViewCompat.isLaidOut(this) && isShown()
.Full method:
By using a custom view extending SwitchCompat, I found out, that
isShown()
always returnsfalse
, because the at third iteration of thewhile
,parent == null
.Interestingly, the third parent is the second attribute passed to
getView(View convertView, ViewGroup parent)
in Preference, means the PreferenceGroupAdapter didn't get a parent passed to its owngetView()
. Why this happens exactly and why this happens only for custom preference classes, I don't know.For my testing purposes, I used the CheckBoxPreference with a SwitchCompat as
widgetLayout
, and I also didn't see animations.Fix
Now to the fix: simply make your own view extending SwitchCompat, and override your
isShown()
like this:Use this SwitchView for your
widgetLayout
style, and animations work again :DStyles:
Widget layout:
i manage to fix it like this and animations is working before it was going to the state directly without animation:
FIX:
CustomSwitchCompat.class
In your layout do this: preference_switch_layout.xml
and in your preference.xml do this:
public class SwitchPreference extends android.preference.SwitchPreference {
Sometimes Extending from a Class is not the best solution. To avoid loosing the animations you could instead Compose it, I meant creating a Class where you have a SwitchPreference field variable and apply the new logic to it. It's like a wrapper. This worked for me.