Android AppCompat v21 provides SwitchCompat does not provide SwitchCompatPerefrence

Deadly 提交于 2019-12-03 05:32:39
TiborP

Based on the currently accepted answer, and cgollner's gist, if you only take the xml layout from there: https://gist.github.com/cgollner/3c7fe2f9d34aee38bd0c

And do this:

<CheckBoxPreference
            android:widgetLayout="@layout/preference_switch_layout"
            android:defaultValue="off"
            android:key="key1"
            android:title="@string/title1" />

Instead of this (adding the layout from source with setWidgetLayoutResource):

<com.cgollner.unclouded.preferences.SwitchCompatPreference
            android:defaultValue="off"
            android:key="key1"
            android:title="@string/title1" />

Then the animations will also work both on lollipop and below using the same xml.

I build a little something for myself, SwitchCompatPreference.java. Extending SwitchPreference turned out to be the easiest way to build this. Sadly, SwitchCompat doesn't inherit from Switch, so the original SwitchPreference requires a slight modification. The preference is used as follows:

<me.barrasso.android.volume.ui.SwitchCompatPreference
        android:icon="@drawable/icon"
        android:key="key"
        android:defaultValue="false"
        android:widgetLayout="@layout/pref_switch"
        android:title="@string/title"
        android:summary="@string/summary" />

The layout is super-simple, tweak it as needed.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.SwitchCompat
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/toggle"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:textIsSelectable="false"
    android:textStyle="bold" />

You're not going to like this answer but the best way I can think of is to create your own preference from the SwitchCompat object:

http://developer.android.com/guide/topics/ui/settings.html#Custom

I know this answer isn't the best, and there are no code samples yet. I will try to work on it over the weekend and update this answer with what I find.

CONS: May not work on every device.


Use AppCompatDelegate in your PreferenceActivity (you can base off the class from AppCompatPreferenceActivity) and override the onCreateView to return SwitchCompat while creating a Switch view

i.e.,

public abstract class AppCompatPreferenceActivity extends PreferenceActivity {
    private AppCompatDelegate mDelegate;

    //... other methods omitted for clarity

    @Override
    public View onCreateView(String name, Context context, AttributeSet attrs) {
        // Allow super to try and create a view first
        final View result = super.onCreateView(name, context, attrs);
        if (result != null) {
            return result;
        }

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            switch (name) {
                // ... can add other views here
                case "Switch":
                    return new SwitchCompat(this, attrs);
            }
        }
        return null;
    }
}

The advantage is that, this way you can add support existing apps without changing your layouts, and minimal effort.

This is about the animation for SwitchCompat widget in accepted answer.

I found that the problem is caused by a flag in Preference class, in Android 4.0-4.3, the flag is mHasSpecifiedLayout, in Android 4.4 the flag is mCanRecycleLayout.

When you set the widget using setWidgetLayoutResource, it will change this flag.

If you create a new customized preference class using different package name(except android.preference or com.android), it will also change this flag.

When mHasSpecifiedLayout is false or CanRecycleLayout is true, the animation will work, otherwise the animation does not work.

So you can set the widget layout using reflection instead of setWidgetLayoutResource() method, then the animation will not be broken.

Here is a snippet:

        CheckBoxPreference switchPref = new CheckBoxPreference(getActivity());
        try {
            Field field = Preference.class.getDeclaredField("mWidgetLayoutResId");
            field.setAccessible(true);
            field.setInt(switchPref, R.layout.preference_switch_layout);
        } catch (Exception e) {
            switchPref.setWidgetLayoutResource(R.layout.preference_switch_layout);
        }
        switchPref.setKey(key);
        switchPref.setTitle(titleRes);
        switchPref.setSummary(summaryRes);
        switchPref.setDefaultValue(defaultValue);
ScheerMT

From the official Android blog:

How do I use AppCompat with Preferences?
You can continue to use PreferenceFragment in your ActionBarActivity when running on an API v11+ device. For devices before that, you will need to provide a normal PreferenceActivity which is not material-styled.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!