Android:创建自定义偏好设置

60

PreferenceScreen中创建个性化偏好设置是否可能?

我想编写像这样的颜色设置:

Color Preference

我知道使用ListPreference很容易选择颜色,但有那种“复选框”会更好。

5个回答

92
Android开发者页面只展示了如何创建一个DialogFragment。但是,你仍然可以自定义Preference项的外观。在XML中,你需要将根元素声明为android:id="@android:id/widget_frame",然后将TextView声明为android:titleandroid:summary。之后,你可以声明其他想要出现在布局中的元素。以下是一个示例,显示了一个SeekBar,你可以将其轻松地调整为多选框颜色选择器。 seekbar_preference.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/widget_frame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@android:id/title"
        style="@android:style/TextAppearance.DeviceDefault.SearchResult.Title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Title" />

    <TextView
        android:id="@android:id/summary"
        style="@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Summary" />

    <SeekBar
        android:id="@+id/seekbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

然后,在一个从Preference派生的类中,重写onCreateView()方法:

SeekbarPreference.java

@Override
protected View onCreateView( ViewGroup parent )
{
  LayoutInflater li = (LayoutInflater)getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE );
  return li.inflate( R.layout.seekbar_preference, parent, false);
}

然后在preferences.xml文件中使用以下偏好设置:

preferences.xml

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <com.example.SeekbarPreference
        android:key="pref_max_volume"
        android:title="@string/max_volume" />
    <com.example.SeekbarPreference
        android:key="pref_balance"
        android:title="@string/balance" />

</PreferenceScreen>

这会创建一个如下所示的偏好设置:

SeekBar preference item

你可以轻松地将此方法调整为在同一行上显示多个复选框,就像原始问题中那样。


我想知道如何制作这样一个自定义首选项,其中颜色被禁用了... 有人知道吗? - Ewoks
在这个例子中,onCreateView() 被调用了两次,你应该调用 super.onCreate() - theroom101
1
请注意,SeekBarPreference的布局实际上可以在此处找到:<andorid-sdk>/platforms/android-24/data/res/layout/preference_widget_seekbar.xml。Android布局不使用widget_frame ID作为根元素,为什么您要这样做?实际上,在XML中有一个注释说“首选项应将其实际的首选项小部件放置在此处”,该注释位于标题和摘要TextView之后,但在具有ID widget_frame'LinearLayout之前。 - user905686
1
你好,感谢这份精彩的指南。我有一个疑问,如果我想更改标题和摘要的值,并在布局上实现点击监听器,应该如何操作?谢谢! - Z. Kiwan
1
为了使布局与其他内置首选项相匹配,您可以在此处找到最新的AndroidX首选项布局:https://android.googlesource.com/platform/frameworks/support/+/androidx-master-dev/preference/preference/res/layout/preference.xml。复制它,修改它,并在更新AndroidX时注意更改。 - now
显示剩余2条评论

50

这是我的做法,使用支持库preference-v7

preference

layout/preference_theme.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <Button android:id="@+id/theme_light" ... />
    <Button android:id="@+id/theme_dark"... />
    <Button android:id="@+id/theme_sepia"... />
    <Button android:id="@+id/theme_green"... />
</LinearLayout>

PreferenceTheme.java(自定义首选项类)

import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceViewHolder;

public class PreferenceTheme extends Preference {

    public PreferenceTheme(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PreferenceTheme(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setWidgetLayoutResource(R.layout.preference_theme);
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder holder) {
        super.onBindViewHolder(holder);
        holder.itemView.setClickable(false); // disable parent click
        View button = holder.findViewById(R.id.theme_dark);
        button.setClickable(true); // enable custom view click
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // persist your value here
            }
        });
        // the rest of the click binding
    }
}

preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.v7.preference.PreferenceCategory
        android:title="Reading">
        <example.com.preference.PreferenceTheme
            android:key="pref_theme"
            android:title="Theme"
            android:defaultValue="light" />
        ...
    </android.support.v7.preference.PreferenceCategory>
</android.support.v7.preference.PreferenceScreen>

1
你能给我一些提示如何在PreferenceActivity中使用构造函数参数(上下文和属性)以及findPreference来创建和使用PreferenceTheme实例吗? - Sdghasemi
4
еҰӮжһңжӮЁж„ҹе…ҙи¶ЈпјҢжҲ‘еҶҷдәҶдёҖзҜҮе…ідәҺеҰӮдҪ•дҪҝз”Ёpreference-v7зҡ„еҚҡе®ўж–Үз« пјҢжӮЁеҸҜд»ҘеңЁиҝҷйҮҢйҳ…иҜ»пјҡhttp://www.hidroh.com/2015/11/30/building-custom-preferences-v7/гҖӮ - hidro
1
如果我使用androidx而不是support库,我该如何应用它? - Anton Makov

8

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅链接的答案可能会失效。-【来自审查】 - Rob
考虑到这个答案是来自2013年,而安卓已经发布了数十个API更新,这可能实际上是一件好事 :) 但我明白你的意思。 - tbkn23

6
您可以为首选项创建自定义布局,并在res/xml中的Preference中设置它,如下所示:android:layout属性。
<Preference
    ......................
    android:layout="@layout/your_layout" />

或者您可以使用Activity而不是Preference。


如果我们正在尝试创建自定义EditTextPreference,则使用android:layout="@layout/your_layout"将不会在对话框中显示它,而是直接显示在主屏幕上。 - Rishabh Srivastava
1
我不明白的是,如何将偏好设置与你布局中的例如Spinner相结合? - N Jay
我猜我们永远不会知道。 - Denny
如果我想要更新your_layout元素,我该如何做? - 007

0

或者更好的选择是扩展DialogPreference类。您可以将颜色选择器小部件设置为对话框视图,并在扩展的首选项本身中获取积极结果。这里有一个类似的问题,但它非常适用于您的情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接