自定义您的设置 Android Jetpack 的一部分。

本文档介绍了如何在层次结构中自定义 Preference 对象。

查找偏好设置

如需访问单独的 Preference(例如在获取或设置 Preference 值时),请使用 PreferenceFragmentCompat.findPreference()。此方法会在整个层次结构中搜索具有指定键的 Preference

例如,如需访问键为 "signature"EditTextPreference,请执行以下操作:

<EditTextPreference
        app:key="signature"
        app:title="Your signature"/>

使用以下代码检索此 Preference

Kotlin

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    setPreferencesFromResource(R.xml.preferences, rootKey)
    val signaturePreference: EditTextPreference? = findPreference("signature")
    // Do something with this preference.
}

Java

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    setPreferencesFromResource(R.xml.preferences, rootKey);
    EditTextPreference signaturePreference = findPreference("signature");
    // Do something with this preference.
}

控制偏好设置可见性

您可以控制用户导航到设置屏幕时可以看到哪些 Preference 对象。例如,如果某个 Preference 仅在对应的功能启用时才有意义,不妨在该功能停用时隐藏该 Preference

如需仅在满足条件时显示 Preference,请先在 XML 中将 Preference 可见性设置为 false,如以下示例所示:

<EditTextPreference
        app:key="signature"
        app:title="Your signature"
        app:isPreferenceVisible="false"/>

onCreatePreferences() 中,当满足相应条件时显示 Preference

Kotlin

override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    setPreferencesFromResource(R.xml.preferences, rootKey)
    if(/*some feature*/) {
        val signaturePreference: EditTextPreference? = findPreference("signature")
        signaturePreference?.isVisible = true
    }
}

Java

@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
    setPreferencesFromResource(R.xml.preferences, rootKey);
    if(/*some feature*/) {
        EditTextPreference signaturePreference = findPreference("signature");
        if (signaturePreference != null) {
            signaturePreference.setVisible(true);
        }
    }
}

动态更新摘要

保留数据的 Preference 必须在其摘要中显示当前值,以帮助用户更好地了解 Preference 的当前状态。例如,EditTextPreference 必须显示保存的文本值,ListPreference 必须显示所选的列表条目。您可能还有 Preference 对象需要根据内部或外部应用状态更新其摘要,例如显示版本号的 Preference。您可以使用 SummaryProvider 来实现此目的。

使用 SimpleSummaryProvider

ListPreferenceEditTextPreference 包含一个自动将已保存的 Preference 值显示为摘要的简单 SummaryProvider 实现。如果未保存任何值,则会显示“未设置”。

如需从 XML 启用这些实现,请设置 app:useSimpleSummaryProvider="true"

或者,您也可以通过代码启用:使用 ListPreference.SimpleSummaryProvider.getInstance()EditTextPreference.SimpleSummaryProvider.getInstance() 获取简单的 SummaryProvider 实例,然后在 Preference 上进行设置,如以下示例所示:

Kotlin

listPreference.summaryProvider = ListPreference.SimpleSummaryProvider.getInstance()
editTextPreference.summaryProvider = EditTextPreference.SimpleSummaryProvider.getInstance()

Java

listPreference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance());
editTextPreference.setSummaryProvider(EditTextPreference.SimpleSummaryProvider.getInstance());

使用自定义 SummaryProvider

无论 Preference 何时提出摘要请求,您都可以创建自己的 SummaryProvider 并替换 provideSummary(),以便对摘要进行自定义。例如,以下 EditTextPreference 会将已保存值的长度显示为摘要:

显示 EditTextPreference 示例的图片
图 1. 示例 EditTextPreference

举例来说,假设存在以下 EditTextPreference

<EditTextPreference
        app:key="counting"
        app:title="Counting preference"/>

onCreatePreferences() 中,您可以创建新的 SummaryProvider 并替换 provideSummary(),以返回要显示的摘要:

Kotlin

val countingPreference: EditTextPreference? = findPreference("counting")

countingPreference?.summaryProvider = SummaryProvider<EditTextPreference> { preference ->
    val text = preference.text
    if (text.isNullOrEmpty()) {
        "Not set"
    } else {
        "Length of saved value: " + text.length
    }
}

Java

EditTextPreference countingPreference = findPreference("counting");

if (countingPreference != null) {
    countingPreference.setSummaryProvider(new SummaryProvider<EditTextPreference>() {
        @Override
        public CharSequence provideSummary(EditTextPreference preference) {
            String text = preference.getText();
            if (TextUtils.isEmpty(text) || text == null){
                return "Not set";
            }
            return "Length of saved value: " + text.length();
        }
    });
}

Preference 摘要会显示已保存值的长度,如果不存在已保存值,则显示“Not set”。

自定义 EditTextPreference 对话框

EditTextPreference 对话框中,您可以通过附加 OnBindEditTextListener 来自定义文本字段行为。系统在向用户显示对话框时会调用此监听器。

例如,您可以自定义对话框以仅接受数字。首先,创建 EditTextPreference

<EditTextPreference
        app:key="number"
        app:title="Numbers only preference"/>

接下来,在 onCreatePreferences() 中创建一个新的 OnBindEditTextListener 并替换 onBindEditText(),以自定义系统向用户显示的 EditText

Kotlin

val numberPreference: EditTextPreference? = findPreference("number")

numberPreference?.setOnBindEditTextListener { editText ->
    editText.inputType = InputType.TYPE_CLASS_NUMBER
}

Java

EditTextPreference numberPreference = findPreference("number");

if (numberPreference != null) {
    numberPreference.setOnBindEditTextListener(
            new EditTextPreference.OnBindEditTextListener() {
                @Override
                public void onBindEditText(@NonNull EditText editText) {
                    editText.setInputType(InputType.TYPE_CLASS_NUMBER);
                }
            });
}

现在,当系统向用户显示对话框时,键盘会以纯数字模式打开,因此用户只能在 EditText 中输入数字。

偏好设置操作

在点按时,Preference 可产生特定操作。例如,Preference 可以充当指向应用单独部分的链接。如需向 Preference 添加操作,您可以直接在 Preference 上设置 Intent,或者为更具体的逻辑设置 OnPreferenceClickListener

设置 Intent

您可以在 Preference 上设置 Intent,以在每次点按 Preference 时启动新的 FragmentActivity 或单独的应用。这与将 Context.startActivity() 与给定 Intent 一起使用的效果相同。

您可以使用嵌套 <intent> 标记在 XML 中设置 Intent。以下示例定义了启动 ActivityIntent

<Preference
        app:key="activity"
        app:title="Launch activity">
    <intent
            android:targetPackage="com.example"
            android:targetClass="com.example.ExampleActivity"/>
</Preference>

或者,您也可以直接在 Preference 上使用 setIntent(),如下所示:

Kotlin

val intent = Intent(context, ExampleActivity::class.java)
activityPreference.setIntent(intent)

Java

Intent intent = new Intent(getContext(), ExampleActivity.class);
activityPreference.setIntent(intent);

您还可以使用 XML 为 Intent 添加 extra:

<Preference
        app:key="activity"
        app:title="Launch activity">
    <intent
            android:targetPackage="com.example"
            android:targetClass="com.example.ExampleActivity">
        <extra
                android:name="example_key"
                android:value="example_value"/>
    </intent>
</Preference>

以下为 Preference 的示例,其中带有启动网页的 Intent

<Preference
        app:key="webpage"
        app:title="View webpage">
    <intent
            android:action="android.intent.action.VIEW"
            android:data="http://www.google.com" />
</Preference>

Kotlin

val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("http://www.google.com")

val webpagePreference = findPreference("webpage")
webpagePreference?.intent = intent

Java

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.google.com"));
webpagePreference.setIntent(intent);

OnPreferenceClickListener

您可以在 Preference 上设置 OnPreferenceClickListener,这会在点按 Preference 时向 onPreferenceClick() 添加回调。例如,如果您有更复杂的逻辑可以用于处理导航,则可以使用监听器导航到另一个 FragmentActivity

如需设置 OnPreferenceClickListener,请使用与下方所示内容类似的代码:

Kotlin

onClickPreference.setOnPreferenceClickListener({
    // Do something.
    true
})

Java

onClickPreference.setOnPreferenceClickListener(preference -> {
    // Do something.
    return true;
});