gpt4 book ai didi

android - 如何为从 2.X 到 4.X 的所有 Android 版本使用相同的首选项屏幕集?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:21:06 27 4
gpt4 key购买 nike

注意:请节省一些时间并引用已接受的答案,无需阅读所有问题。
您可以阅读问题的其余部分以及我为替代(尽管不太复杂)方法提供的答案。
此外,您可能希望通过将相关代码添加到您的偏好 Activity 类来利用对 Android 2.X 中后台故障的修复。

背景
作为 Android 编码的新手,但在其他编程语言/框架方面有些经验,我希望我对 Android 应用程序编码的探索会是一个相当愉快的过程。原来如此,直到我偶然发现了这个问题:

Android 项目的 Eclipse 向导建议,如果我将最低 API 设置为 8(Android 2.2),我可以达到 95% 的设备。反正我不需要用我的应用程序做任何花哨的事情,所以我想,“当然,为什么不呢?”。一切都很好,除了偶尔我会发现一些在最近的 API 版本中被弃用的方法/类,所以我不得不想办法继续使用旧设备的旧方法,并尝试尽可能多地使用新的适用于较新 Android 版本的方法。这是一个这样的场合。

在使用 Eclipse 向导创建首选项 Activity 后,我意识到 Eclipse 预编译器/解析器/检查器(或任何名称)Lint 会提示无法使用旧 API 版本中创建/管理首选项的新方法。所以我想,“好吧,搞砸新方法。让我们用旧方法来做,因为新的 API 版本应该是向后兼容的,所以应该没问题”,但事实并非如此。旧方式使用标记为已弃用的方法/类;对我来说,这意味着,即使它们仍然可以在当前的 API 中工作,它们也会在 future 版本的某个时候停止工作。

所以我开始寻找正确的方法来做到这一点,最后点击了这个页面:What to use instead of "addPreferencesFromResource" in a PreferenceActivity? Garret Wilson 解释了一种以与新方式兼容的方式使用旧首选项屏幕资源的方法。太棒了,终于感觉我可以继续我的应用程序编码了,除非它在针对旧 API 时不起作用,因为它使用的是更新的 API 代码。因此,我必须设计一种方法,使其既适用于旧 API,也适用于新 API。在修改了一段时间后,我设法找到了一种方法,通过使用预编译器(或其他任何名称)注释和很棒的 getClass().getMethod() 以及异常。

一切似乎都完美无缺,直到我创建了一个偏好子屏幕。它在较新的 Android 版本中正确显示,但是当我在较旧的版本中尝试时,我只能看到黑屏。经过多次搜索,我找到了解释问题的页面:http://code.google.com/p/android/issues/detail?id=4611这显然是一个已知的故障,它已经在几个 Android 版本中存在了很长一段时间。我阅读了整个线程并找到了几个针对该问题的建议解决方案,但我真的不完全喜欢它们中的任何一个。一方面,我更喜欢尽可能避免静态的东西,并以编程方式做事。与重复性工作相比,我更喜欢自动化。一些解决方案建议创建子屏幕作为父屏幕,然后将它们添加到 list 文件中,并通过 Intent 从父屏幕调用它们。我真的很讨厌必须跟踪这些事情: list 中的条目、分离的屏幕资源文件、 Intent ……所以这对我来说是禁忌。我一直在寻找并找到了一种我更喜欢的程序化方法……却发现它不起作用。它包括遍历首选项屏幕的整个 View 树并为首选项子屏幕分配适当的背景,但它不起作用,因为我后来在多次调试后发现,首选项子屏幕 View 不是偏好屏幕 View 的子级。我必须自己找到一种方法来实现这一目标。我尝试了我能想到的尽可能多的东西,研究和研究无济于事。我曾多次处于放弃的边缘,但经过大约两周的持续努力和大量调试后,我找到了一个解决方法,并将其发布在评论 #35 中。

意见
它确实不是完美的解决方案/方法,我知道它的一些缺点,但它是有效的,所以我决定分享它。希望我的热情不会太荒谬,无法分享让我付出了很多努力的东西,因为我知道这不是什么大问题,任何有经验的编码人员都可以解决。但是,嘿,我认为分享知识让我变得更好一点,无论我吹嘘多少,都比一个经验丰富的编码员把一切都保密。只是分享我的意见,因为我不敢相信以前没有人遇到过这个问题,但我相信很多人都遇到过这个问题,并且不愿意分享他们的知识。

我在答案中为您提供了一个建议的类,用于在多个版本的 Android 上使用,以及一些有关其使用的建议。我愿意讨论和贡献,以使其成为更好的类(class)。

已知问题:

  • 父屏幕装饰 View 背景被克隆到子屏幕装饰 View 背景上,这显然不是正常行为。
    状态:被解雇,直到有人提出一个很好的理由来解决这个问题
  • 屏幕旋转时崩溃
    状态:固定。
    可能与较新的 API 实现(内部类 PF)的资源可见性有关
    显然从preferenceFragment 继承的类需要让它们的所有成员都是静态的。我想如果每次需要使用新 fragment 时都应该继承是有道理的
  • 最佳答案

    如果您使用的是最新的 ADT 插件,则可以选择轻松创建支持大多数旧 Android 版本以及所有新版本的偏好 Activity 。

    Right click on your project -> Other -> Android Activity



    然后选择 SettingsActivity
    enter image description here

    创建的 Activity 将负责处理高和低 API 版本,因为它使用 if 语句来选择显示首选项的适当方法。

    编辑
    提出了一个好观点:手机大小的设备,无论 API 版本如何,都使用旧的 PreferenceActivity方法。

    让 API 11+ 设备使用的最快方法 Fragments是删除 !isXLargeTablet(context);来自 isSimplePreferences()
    private static boolean isSimplePreferences(Context context) {
    return ALWAYS_SIMPLE_PREFS
    || Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB;
    }

    但是,现在用户有更多的导航要做。
    Headers as root

    这是因为 onBuildHeaders()叫做。

    为了摆脱这种情况,我们需要制作我们自己的 PreferenceFragment 来添加每个 xml 资源。
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public static class AllPreferencesFragment extends PreferenceFragment{
    @Override
    public void onCreate (Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.pref_general);

    // Add 'notifications' preferences, and a corresponding header.
    PreferenceCategory fakeHeader = new PreferenceCategory(getActivity());
    fakeHeader.setTitle(R.string.pref_header_notifications);
    getPreferenceScreen().addPreference(fakeHeader);
    addPreferencesFromResource(R.xml.pref_notification);

    // Add 'data and sync' preferences, and a corresponding header.
    fakeHeader = new PreferenceCategory(getActivity());
    fakeHeader.setTitle(R.string.pref_header_data_sync);
    getPreferenceScreen().addPreference(fakeHeader);
    addPreferencesFromResource(R.xml.pref_data_sync);

    // Bind the summaries of EditText/List/Dialog/Ringtone preferences to
    // their values. When their values change, their summaries are updated
    // to reflect the new value, per the Android Design guidelines.
    bindPreferenceSummaryToValue(findPreference("example_text"));
    bindPreferenceSummaryToValue(findPreference("example_list"));
    bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone"));
    bindPreferenceSummaryToValue(findPreference("sync_frequency"));
    }
    }

    如果可以从 Activity之外确定屏幕尺寸启动设置,您可以指定一个 fragment 以通过 EXTRA_SHOW_FRAGMENT 启动它
    i.putExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT, "com.example.test.SettingsActivity$AllPreferencesFragment");

    或者您可以拥有 SettingsActivity确定是否显示此 Fragment(假设您对 isXLargeTablet() 方法感到满意。

    更改 onBuildHeaders()到:
    @Override
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    public void onBuildHeaders(List<Header> target) {
    if (!isSimplePreferences(this) && isXLargeTablet(this)) {
    loadHeadersFromResource(R.xml.pref_headers, target);
    }
    }

    添加此方法:
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void setupNewApiPhoneSizePreferences() {
    if (!isXLargeTablet(this) && Build.VERSION.SDK_INT > Build.VERSION_CODES.HONEYCOMB){
    getFragmentManager().beginTransaction().replace(android.R.id.content, new AllPreferencesFragment()).commit();
    }
    }

    而在 onPostCreate()添加方法调用。
    setupNewApiPhoneSizePreferences();

    这现在应该使用从 API 11 开始的非弃用调用。

    关于android - 如何为从 2.X 到 4.X 的所有 Android 版本使用相同的首选项屏幕集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14076073/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com