nLL
nLL

Reputation: 5672

Android AppCompat v21 provides SwitchCompat does not provide SwitchCompatPreference

It seems AppCompat v21 provides SwitchCompat does not provide SwitchCompatPreference.

I know I can use SwitchPreference but it is not visually identical. On Android 4.x; when I use SwitchCompact from v21 on activity interface, it looks like material switch button, but, because there is no SwitchCompactPreference I have to use SwitchPreference in my preference view and obviously it has Android 4.0 look.

It looks like AppCompact v21 half complete.

Am I missing something?

Upvotes: 14

Views: 6113

Answers (7)

Hexise
Hexise

Reputation: 1568

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);

Upvotes: 1

TiborP
TiborP

Reputation: 467

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.

Upvotes: 10

Avinash R
Avinash R

Reputation: 3151

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.

Upvotes: 1

Tom
Tom

Reputation: 7091

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" />

Upvotes: 6

John Shelley
John Shelley

Reputation: 2655

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.

Upvotes: 3

ScheerMT
ScheerMT

Reputation: 1

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.

Upvotes: -2

Related Questions