如何使用 v7/v14 首选项支持库?

How to use the v7/v14 Preference Support library?

与 M 版本一起,还有新的支持库。其中一个似乎非常有用的是 v7 Preference Support 库。

好像没有PreferenceActivity之类的东西,我们如何将它集成到我们的应用程序中?

你是对的,它在 appcompat v7 上不存在,但 Google 实际上添加了 AppCompatDelegate 抽象 class 作为委托,你可以使用它来将 AppCompat 的支持注入到任何activity。您可以从 this answer.

中找到更多信息

这是一个示例,说明如何从 Google 的 AppCompat 样本中将 AppCompatDelegate 注入到您的 activity,您可以在 here.[=14 中找到它=]

有了新的首选项支持库 v7,您可以将 PreferenceFragmentCompat 与任何 ActivityAppCompatActivity

一起使用
public static class PrefsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.preferences);
    }
}

您必须在您的主题中设置preferenceTheme

<style name="AppTheme" parent="@style/Theme.AppCompat.Light">
  ...
  <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
</style>

通过这种方式,您可以自定义 preferenceTheme 以设置用于每种首选项类型的布局样式,而不会影响 Activity 的其他部分。

您必须扩展片段所需的 AppCompatActivity,并包含 PreferenceFragmentCompat 的子类。抽象片段需要重写一个方法,您应该在其中放置您偏好的 inflation 逻辑。最后,您的 activity 主题需要指定一个 preferenceTheme 属性。

阅读公告 here. With preference-v7 library you can replace PreferenceFragment (API 11+) with PreferenceFragmentCompat subclass, and SwitchPreference (API 14+) with SwitchPreferenceCompat 并让您的设置屏幕从 API 7.

下面是我是如何让它工作的:

SettingsActivity.java

public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);
    }
}

layout/activity_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent" >
    <fragment
        android:name=".SettingsFragment"
        android:tag=".SettingsFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</FrameLayout>

SettingsFragment.java

public class SettingsFragment extends PreferenceFragmentCompat {

    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        addPreferencesFromResource(R.xml.preferences);
    }
}

xml/preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <android.support.v7.preference.PreferenceCategory
        ...>

        <android.support.v7.preference.ListPreference
            ... />

        <android.support.v7.preference.SwitchPreferenceCompat
            ... />

        ...

    </android.support.v7.preference.PreferenceCategory>

    ...

</android.support.v7.preference.PreferenceScreen>

values/styles.xml

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
    ...
</style>

preference-v7 默认主题

<style name="PreferenceThemeOverlay">
    <item name="preferenceScreenStyle">@style/Preference.PreferenceScreen</item>
    <item name="preferenceFragmentStyle">@style/PreferenceFragment</item>
    <item name="preferenceCategoryStyle">@style/Preference.Category</item>
    <item name="preferenceStyle">@style/Preference</item>
    <item name="preferenceInformationStyle">@style/Preference.Information</item>
    <item name="checkBoxPreferenceStyle">@style/Preference.CheckBoxPreference</item>
    <item name="switchPreferenceCompatStyle">@style/Preference.SwitchPreferenceCompat</item>
    <item name="dialogPreferenceStyle">@style/Preference.DialogPreference</item>
    <item name="editTextPreferenceStyle">@style/Preference.DialogPreference.EditTextPreference</item>
    <item name="preferenceFragmentListStyle">@style/PreferenceFragmentList</item>
</style>

我试图用一个 activity 来实现上面 Hidro 的回答,它也包含一个工具栏,由于以下错误,它给了我以下布局 inflation 异常:

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.support.v4.app.FragmentHostCallback.getContext()' on a null object reference

我一直无法解决这些问题,所以采用了以下方法:

public class SettingsActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  if(savedInstanceState == null)
    getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, new SettingsFragment()).commit();
  }
}

SettingsActivity 的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:fitsSystemWindows="true">
  <include layout="@layout/toolbar"/>
  <FrameLayout android:id="@+id/fragment_container"
               android:layout_width="match_parent"
               android:layout_height="match_parent"
               app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

张贴在这里,因为如果其他人遇到同样的异常,它可能会有所帮助

hidro 的回答是正确的,但还有一点需要注意:

只需使用正常的首选项 xml 标签,例如 PreferenceScreen 而不是完整的 class 名称。 支持库会自动转换它们.

原因: 如果您使用完整的 class 名称,代码建议和布局预览将无法正常工作。

所以你应该这样写xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        ...>

        <ListPreference
            ... />

        <SwitchPreferenceCompat
            ... />

        ...

    </PreferenceCategory>

    ...

</PreferenceScreen>