【问题标题】:How to customize list preference radio button如何自定义列表首选项单选按钮
【发布时间】:2012-05-05 09:55:30
【问题描述】:

我已自定义应用程序中的所有单选按钮,但 listPreference 中的单选按钮未自定义。

我使用了这个名为 btn_radio.xml 的 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>

这是扩展 android 自定义单选按钮的 customRadioButton

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

此更改自定义了我的应用程序中的所有单选按钮,除了我的 ListPreference 中的单选按钮

【问题讨论】:

    标签: android radio-button customization listpreference


    【解决方案1】:

    无法直接从 XML 中设置 ListPreference 的样式。问题是ListPreference(通过DialogPreference)调用AlertDialog.Builder(Context) 来构建它的Dialog,而不是AlertDialog.Builder(Context context, int themeResourceId)。虽然后者允许提供主题,但前者不允许,导致它回退到默认的 Android 主题。

    对于一个项目,我需要一个带有自定义标题颜色、自定义单选按钮样式和自定义 ListView 选择器的 ListPreference(基本上是不同颜色的 Holo)。我通过扩展ListPreference 并覆盖onPrepareDialogBuilder(Builder)OnCreateDialogView() 解决了这个问题,因此我可以使用带有简单ArrayAdapter 的自定义ListView,而不是Dialog 的内置ListView(它不支持造型)。我还必须覆盖 onDialogClosed() 以便为首选项设置正确的值。

    为了使用它,您只需将您的preferences.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 可绘制对象,就像您的 android-sdk/platforms/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>
    

    【讨论】:

    • 这里的CheckedTextView 是什么,是否创建了任何自定义视图。请指导一下。
    • R.layout.btn_radio 布局中应该包含什么。
    • @NidhiGondhia, CheckedTextView 是一个标准的 Android 小部件。以&lt;CheckedTextView... 开头的代码 sn-p 应该在R.layout.btn_radio 中。而不是btn_radio,一个更好的名字可能是list_item
    • 谢谢。我正在寻找几个小时来获得适当的解决方法。这个解决方案是我见过的最好的。这个问题应该被投票为“检查”:)
    • 我认为它不再有效。无法覆盖“onCreateDialogView”。使用 PreferenceFragmentCompat。
    【解决方案2】:

    请看我的回答here,也许有帮助。

    这是解决问题的一种更简单的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      • 2014-08-19
      • 2023-03-30
      • 2020-07-21
      • 1970-01-01
      • 2015-03-21
      相关资源
      最近更新 更多