是否有意将PreferenceFragment从兼容性包中排除?


153

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

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

干杯

詹姆士


1
这是我的方法来解决这个问题:stackoverflow.com/questions/14076073/...
ECV

有人创建了第三方PreferenceFragment,您甚至会忘记它。看我的回答
theblang 2014年

克里斯·巴内斯(Chris Banes)在其博客中的评论中谈到了这一点。他说原因是,"Because most of Preferences' implementation is hidden, therefore impossible to backport without lots of hackery."
theblang

请参阅我的最新答案PreferenceFragmentCompat是最近添加到支持库的。
theblang

Answers:


90

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

自Android 3.0起不推荐使用不推荐使用的方法。它们在所有版本的Android上都很好,但方向是PreferenceFragment在Android 3.0及更高版本上使用。

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

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

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

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

如果没有有意排除它,我们是否可以期望新版本的兼容软件包?

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

还是有其他可以安全使用的解决方法?

往上看。


干杯马克。我已经看到您在几个地方(android google小组和您的博客)对此进行了评论,但是想要一个明确的答案(就情况而定)。
詹姆斯

@James:是的,麻烦在于优先级XML定义中,因为某些不确定性可以与优先级XML一起使用,所以可以将某些东西作为片段很好地工作,也可以连接在一起<include>。顺便说一句,如果您是订户,则引用该项目的书籍更新已在几分钟前宣布。
CommonsWare

7
对不起,但我不确定我要在这里提出什么观点。您根本不回答任何问题,只需评论/猜测/引用与问题无关的无关外部链接。问题是是否遗漏是故意的,如果没有 PreferenceFragment的兼容版本,就无法以您描述的方式扩展PreferenceActivity,因为如果PreferenceFragment不存在,那么getSupportFragmentManager()或任何其他方法都不会首先需要使用片段。
贾斯汀·布什

8
@JustinBuser:“问题是遗漏是否是有意的” –唯一可以为Google回答该问题的人。欢迎您在Google找到一份工作以尝试找出答案。“无法以您所描述的方式扩展PreferenceActivity” –欢迎下载我链接到的代码。
CommonsWare,2012年

9
@JustinBuser记录下来,Mark确实回答了我的问题。从我接受他的回答中可以明显看出这一点。
詹姆斯

21

@CommonsWare的答案的隐含含义是-您的应用程序必须在兼容性API或内置片段API之间进行选择(因为SDK 11左右)。实际上,这就是“轻松”建议所做的。换句话说,如果要使用PreferenceFragment,则您的应用程序需要使用内置的片段API并处理PreferenceActivity上已弃用的方法。相反,如果您的应用使用compat很重要。您将面对的API根本就没有PreferenceFragment类。因此,定位设备不是问题,但是当您必须选择一个或另一个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交换。有趣的日志!


让我更直接一点。如果您只关心目标是Honeycomb或更高版本(具有多少市场份额?),请投票@Commonsware的答案!如果您关心当今市场上的大多数Android设备,则应阅读我的回复。
顽强的

4
您愿意分享您的做法吗?我遇到了完全相同的问题,只有PreferenceActivity必须使用Loaders,因此我必须使用兼容性库。
卡拉库里

3
@Tenacious我喜欢你的调查-做得好。但是,我觉得有人应该直接在您的第一个评论上保持记录-Commonsware的代码将在HC之前和之后的设备上工作-请先尝试,然后再进行此类评论。您需要实现的是在运行时使用后期绑定来支持以前的设备。在运行时进行版本检查可同时支持两种操作系统-这是一种常见的Android模式(我不喜欢这种模式-但对于Android开发人员学习和熟悉这一模式很重要)...因此,对于未来的读者-不要不要忽略任何一种方法。
理查德·勒·马修里尔

如果你需要内部DrawerLayout喜好@RichardLeMesurier但Commonsware的方法是不妥当的
新世界

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的模拟器上进行了测试。



10

Google在2015年8月发布了新的首选项支持库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以设置每种首选项类型所用布局的样式,而不会影响“活动”的其他部分。


1
我认为您错过了一个功能:onCreatePreferences
Android开发人员

这挽救了我的一天!我不知道为什么这在Android Studio的项目结构中不可见...?顺便说一句,您的代码中有错字。应该是“扩展PreferenceFragmentCompat”
Grzegorz D.

7

顽强的答案是正确的,但是这里有更多详细信息。

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

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

而且,您无法通过将实现轻松地放入android.preferences包中来解决此问题,因为SDK中实际上省略了Android API中的非公共方法。借助涉及反射和动态代理的一些创造力,您仍然可以使用它们。正如Tenacious所说,唯一的选择是派生整个android.preference包,包括至少15个类,5个布局以及相似数量的style.xml和attrs.xml元素。

因此,为了回答最初的问题,Google在兼容性软件包中未包含PreferenceFragment的原因是,他们与Tenacious和我本人将面临完全相同的困难。甚至Google都无法回到过去,并在旧平台上公开这些方法(尽管我希望它们在将来的版本中可以做到)。


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();
    }
}

2

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

经过一番搜索,我发现了android-support-v4-preferencefragment lib。正如Tenacious所说,此lib节省了大量复制和重构原始PreferencesFragment的时间。效果很好,用户喜欢使用偏好。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.