How to customize list preference radio button How to customize list preference radio button android android

How to customize list preference radio button


Styling the ListPreference from XML is not directly possible. The problem is that ListPreference (through DialogPreference) calls AlertDialog.Builder(Context) to build its Dialog, rather than AlertDialog.Builder(Context context, int themeResourceId). While the latter allows for providing a theme, the former does not, causing it to fall back to a default Android theme.

For a project, I needed a ListPreference with a custom title-color, a custom radiobutton-style and a custom ListView-selector (basically, Holo in a different color). I solved this by extending ListPreference and overriding onPrepareDialogBuilder(Builder) and OnCreateDialogView() so I could use a custom ListView with a simple ArrayAdapter, rather than Dialog's built-in ListView (which doesn't have support for styling). I also had to override onDialogClosed() in order to set the right value to the preference.

In order to use it, all you have to do is replace the classname of the preference in your preferences.xml rom ListPreference to com.your.packagename.ThemedListPreference. Other than that, the implementation is identical to ListPreference.

public class ThemedListPreference extends ListPreference implements OnItemClickListener {    public static final String TAG = "ThemedListPreference";    private int mClickedDialogEntryIndex;    private CharSequence mDialogTitle;    public ThemedListPreference(Context context, AttributeSet attrs) {        super(context, attrs);    }    public ThemedListPreference(Context context) {        super(context);    }    @Override    protected View onCreateDialogView() {        // inflate custom layout with custom title & listview        View view = View.inflate(getContext(), R.layout.dialog_settings_updatetime, null);        mDialogTitle = getDialogTitle();        if(mDialogTitle == null) mDialogTitle = getTitle();        ((TextView) view.findViewById(R.id.dialog_title)).setText(mDialogTitle);        ListView list = (ListView) view.findViewById(android.R.id.list);        // note the layout we're providing for the ListView entries        ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(                getContext(), R.layout.btn_radio,                getEntries());        list.setAdapter(adapter);        list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);        list.setItemChecked(findIndexOfValue(getValue()), true);        list.setOnItemClickListener(this);        return view;    }    @Override    protected void onPrepareDialogBuilder(Builder builder) {        // adapted from ListPreference        if (getEntries() == null || getEntryValues() == null) {            // throws exception            super.onPrepareDialogBuilder(builder);            return;        }        mClickedDialogEntryIndex = findIndexOfValue(getValue());        // .setTitle(null) to prevent default (blue)        // title+divider from showing up        builder.setTitle(null);        builder.setPositiveButton(null, null);    }    @Override    public void onItemClick(AdapterView<?> parent, View view, int position,            long id) {        mClickedDialogEntryIndex = position;        ThemedListPreference.this.onClick(getDialog(), DialogInterface.BUTTON_POSITIVE);        getDialog().dismiss();    }    @Override    protected void onDialogClosed(boolean positiveResult) {            // adapted from ListPreference        super.onDialogClosed(positiveResult);        if (positiveResult && mClickedDialogEntryIndex >= 0                && getEntryValues() != null) {            String value = getEntryValues()[mClickedDialogEntryIndex]                    .toString();            if (callChangeListener(value)) {                setValue(value);            }        }    }}

For my ListView items I used the layout below. Note that drawable/btn_radio_holo_light is an XML-drawable like the one in your android-sdk/platforms/android-x/data/res/drawable folder, only with references to different drawables.

<?xml version="1.0" encoding="utf-8"?><CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/text1"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:checkMark="@drawable/btn_radio_holo_light"    android:gravity="center_vertical"    android:minHeight="@dimen/list_item_minheight"    android:paddingLeft="@dimen/list_item_paddingLeft"    android:paddingRight="@dimen/list_item_paddingLeft" />

For my Dialog layout (onCreateDialogView()), I used the following:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TextView        android:id="@+id/dialog_title"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_margin="16dp"        android:textColor="@color/title_color"        android:textSize="22sp" />    <View        android:layout_width="match_parent"        android:layout_height="2dp"        android:background="@color/divider_color" />    <ListView        android:id="@android:id/list"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:listSelector="@drawable/list_selector" /></LinearLayout>


Please, see my answer here, maybe it helps.

It's a much easier way to solve the problem.