Как настроить переключатель предпочтений списка

Я настроил все radioButtons в своем приложении, но radioButtons в listPreference не настраивается.

Я использовал этот xml с именем btn_radio.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_checked="true" android:state_window_focused="false"
      android:drawable="@drawable/radio_selected" />
<item android:state_checked="false" android:state_window_focused="false"
      android:drawable="@drawable/radio_unselected" />

<item android:state_checked="true" android:state_pressed="true"
      android:drawable="@drawable/radio_selected" />
<item android:state_checked="false" android:state_pressed="true"
      android:drawable="@drawable/radio_unselected" />

<item android:state_checked="true" android:state_focused="true"
      android:drawable="@drawable/radio_selected" />
<item android:state_checked="false" android:state_focused="true"
      android:drawable="@drawable/radio_unselected" />

<item android:state_checked="false" android:drawable="@drawable/radio_unselected" />
<item android:state_checked="true" android:drawable="@drawable/radio_selected" />
</selector>

Это customRadioButton, который расширяет пользовательскую радио-кнопку android

<style name="CustomRadioButton"    Parent="@android:style/Widget.CompoundButton.RadioButton">
    <item name="android:button">@drawable/btn_radio</item>
</style>

в теме моего приложения я сделал эти изменения

<item name="android:radioButtonStyle">@style/CustomRadioButton</item>
    <item name="android:listChoiceIndicatorSingle">@style/CustomRadioButton</item>

Это изменяет настройку всех radioButtons в моем приложении, кроме radioButtons в моем ListPreference

Ответ 1

Укладка ListPreference из XML напрямую не возможна. Проблема в том, что ListPreference (через DialogPreference) вызывает AlertDialog.Builder(Context), чтобы построить его Dialog, а не AlertDialog.Builder(Context context, int themeResourceId). В то время как последний позволяет предоставить тему, первый не делает этого, заставляя его вернуться к теме Android по умолчанию.

Для проекта мне понадобился ListPreference с настраиваемым цветом заголовка, настраиваемым стилем радиообмена и настраиваемым ListView-селектором (в основном, Holo в другом цвете). Я решил это, расширив ListPreference и переопределив onPrepareDialogBuilder(Builder) и OnCreateDialogView(), чтобы я мог использовать пользовательский ListView с простым ArrayAdapter, а не Dialog встроенный ListView (который не поддерживает стилизацию), Мне также пришлось переопределить onDialogClosed(), чтобы установить правильное значение для предпочтения.

Чтобы использовать его, все, что вам нужно сделать, это заменить имя класса предпочтения в ваших предпочтениях. xml rom ListPreference до com.your.packagename.ThemedListPreference. Кроме того, реализация идентична 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);
            }
        }
    }
}

Для моих элементов ListView я использовал макет ниже. Обратите внимание, что drawable/btn_radio_holo_light является XML-drawable, подобным тому, который находится в вашей папке android-sdk/platform/android-x/data/res/drawable, только со ссылками на разные чертежи.

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

В моем макете диалога (OnCreateDialogView()) я использовал следующее:

<?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>