自定义您的设置   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 包含简单的 SummaryProvider 实现,这些实现会自动将保存的 Preference 值显示为摘要。如果没有保存值,它们将显示“未设置”。

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

您可以创建自己的 SummaryProvider 并覆盖 provideSummary() 以在 Preference 请求摘要时自定义摘要。例如,以下 EditTextPreference 将其保存值的长度显示为摘要

An image showing an example 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 摘要显示保存值的长度,或者在没有保存值的情况下显示“未设置”。

自定义 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 或独立应用。这与使用给定 Intent 调用 Context.startActivity() 相同。

您可以使用嵌套的 <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 中包含额外信息

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

以下是一个带有 IntentPreference 的示例,该 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;
});