153

我正在寻找可应用于 3.0 和 3.0 之前的设备的首选项。发现PreferenceActivity包含不推荐使用的方法(尽管在随附的示例代码中使用了这些方法),我查看PreferenceFragement了兼容性包来解决我的问题。

但是,它似乎PreferenceFragment不在兼容性包中。谁能告诉我这是不是故意的?如果是这样,我是否可以轻松定位一系列设备(即 < 3.0 和 >=3.0),还是我必须跳过箍?如果不是有意排除,我们可以期待新版本的兼容性包吗?还是有另一种可以安全使用的解决方法?

干杯

詹姆士

4

8 回答 8

90

发现 PreferenceActivity 包含不推荐使用的方法(尽管在随附的示例代码中使用了这些方法)

自 Android 3.0 起,已弃用的方法已弃用。它们在所有版本的 Android 上都非常好,但方向是PreferenceFragment在 Android 3.0 及更高版本上使用。

谁能告诉我这是不是故意的?

我的猜测是这是一个工程时间问题,但这只是一个猜测。

如果是这样,我是否可以轻松定位一系列设备(即 < 3.0 和 >=3.0),还是我必须跳过箍?

我认为它“容易”完成。有两个单独的PreferenceActivity实现,一个使用首选项标头PreferenceFragments,另一个使用原始方法。在您需要的时候选择正确的选项(例如,当用户单击选项菜单项时)。这是一个演示这个的示例项目。或者,有一个PreferenceActivity可以处理这两种情况的单一项目,如在这个示例项目中。

如果不是有意排除,我们可以期待新版本的兼容性包吗?

当我们其他人发现时,您会发现,也就是说,它是否以及何时发货。

还是有另一种可以安全使用的解决方法?

往上看。

于 2011-03-31T14:41:45.353 回答
21

@CommonsWare 答案的微妙含义是 - 您的应用程序必须在兼容性 API 或内置片段 API 之间进行选择(从 SDK 11 左右开始)。事实上,这就是“轻松”建议所做的事情。换句话说,如果你想使用 PreferenceFragment,你的应用需要使用内置的 Fragment API 并处理 PreferenceActivity 上不推荐使用的方法。相反,如果您的应用程序使用兼容很重要。您将面临根本没有 PreferenceFragment 类的 API。因此,定位设备不是问题,但是当您必须选择一个或另一个 API 并因此将您的设计提交给不可预见的解决方法时,就会发生跳跃。我需要伴侣。API,所以我将创建自己的 PreferenceFragment 类并看看它是如何工作的。在最坏的情况下,我'

编辑:在尝试并查看http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/preference/PreferenceFragment.java 的代码之后? av=h -- 创建我自己的 PreferenceFragment 不会发生。似乎在 PreferenceManager 中自由使用 package-private 而不是“protected”是主要的障碍。看起来确实没有任何安全性或真正好的动机来做到这一点,而且它对于单元测试也不是很好,但是哦,好吧......我想少打字......

编辑 v2:实际上它确实发生了并且有效。让代码与 Compatibility API JAR 一起工作绝对是一件令人头疼的事情。我不得不将大约 70% 的 com.android.preference 包从 SDK 复制到我的应用程序,然后在 Android 中与通常质量一般的 Java 代码搏斗。我使用了 SDK 的 v14。Goog 工程师做我所做的事情会容易得多,这与我听到的一些主要 Android 工程师关于这个话题的说法相反。

顺便说一句 - 我有没有说“定位设备不是问题”?完全是……如果您使用 com.android.preference,您将无法在不进行重大重构的情况下与 Compatibility API 交换。有趣的日志!

于 2012-01-11T09:51:43.780 回答
16

基于 CommonsWare 的回答和 Tenacious 的观察,我提出了一个单一的后代类解决方案,能够以最小的麻烦和没有代码或资源重复的情况下针对所有当前的 Android API 版本。请在此处查看我对相关问题的回答: PreferenceActivity Android 4.0 及更早版本

或在我的博客上:http: //www.blackmoonit.com/2012/07/all_api_prefsactivity/

在运行 4.0.3 和 4.0.4 的两台平板电脑以及运行 4.0.4 和 2.3.3 的手机以及运行 1.6 的模拟器上进行了测试。

于 2012-07-04T22:52:39.927 回答
10

请参阅Machinarius的 PreferenceFragment-Compat。使用 gradle 很容易加入,我忘记了它甚至在那里。

compile 'com.github.machinarius:preferencefragment:0.1.1'

重要更新:现在的最新版本具有v7 support library原生PreferenceFragmentCompat

于 2014-05-08T21:39:12.333 回答
10

2015 年 8 月,Google 发布了新的Preference Support Library 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 的其他部分。

于 2015-09-01T06:49:28.253 回答
7

顽强的回答是正确的,但这里有更多细节。

您不能“创建普通布局并将视图组件手动绑定到 sharedprefs”的原因是 android.preferences API 中有一些令人惊讶的遗漏。PreferenceActivity 和 PreferenceFragment 都可以访问关键的非公共 PreferenceManager 方法,如果没有这些方法,您将无法实现自己的首选项 UI。

特别是,要从 XML 文件构造 Preference 层次结构,您需要使用 PreferenceManager,但 PreferenceManager 的所有构造函数要么是包私有的,要么是隐藏的。将 Preference onClick 侦听器附加到您的活动的方法也是包私有的。

而且你不能通过偷偷地将你的实现放在 android.preferences 包中来解决这个问题,因为 Android API 中的非公共方法实际上从 SDK 中省略了。通过一些涉及反射和动态代理的创造力,你仍然可以得到它们。正如Tenacious 所说,唯一的选择是分叉整个android.preference 包,包括至少15 个类、5 个布局以及相似数量的style.xml 和attrs.xml 元素。

所以要回答最初的问题,谷歌没有在兼容性包中包含 PreferenceFragment 的原因是他们会遇到与 Tenacious 和我完全相同的困难。甚至 Google 也无法及时返回并在旧平台上公开这些方法(尽管我希望他们在未来的版本中这样做)。

于 2013-05-01T12:34:07.983 回答
2

我的应用程序目标是 API +14,但由于使用支持库进行一些花哨的导航,我不能使用android.app.Fragment并且必须使用android.support.v4.app.Fragment,但我还需要PreferenceFragment在不对后面的代码进行大量更改的情况下就位。

所以我很容易解决支持库和两个世界的问题PreferenceFragment

private android.support.v4.app.Fragment fragment;
private android.app.Fragment nativeFragment = null;

private void selectItem(int position) {
    fragment = null;
    boolean useNativeFragment = false;
    switch (position) {
    case 0:
        fragment = new SampleSupprtFragment1();
        break;
    case 1:
        fragment = new SampleSupprtFragment2();
        break;
    case 2:
        nativeFragment = new SettingsFragment();
        useNativeFragment = true;
        break;
    }
    if (useNativeFragment) {
        android.app.FragmentManager fragmentManager = getFragmentManager();
        fragmentManager.beginTransaction()
            .replace(R.id.content_frame, nativeFragment).commit();
    } else {
        if (nativeFragment != null) {
            getFragmentManager().beginTransaction().remove(nativeFragment)
                .commit();
            nativeFragment = null;
        }
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction()
            .replace(R.id.content_frame, fragment).commit();
    }
}
于 2013-08-17T05:40:25.457 回答
2

我需要将 Preferences 集成到应用程序的设计中并保持对 2.3 android 的支持。所以我仍然需要 PreferencesFragment。

经过一番搜索,我找到了android-support-v4-preferencefragment库。正如Tenacious 所说,这个库为复制和重构原始 PreferencesFragment 节省了大量时间。工作正常,用户喜欢偏好。

于 2014-02-20T15:09:47.647 回答