新的首选项支持库在运行时不正确的主题 [英] New Preference support library incorrect theme at runtime

本文介绍了新的首选项支持库在运行时不正确的主题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用新的 Preference v14 支持库.为了给首选项一个材质样式,我在我的 Activity 中使用了以下样式:

I'm trying to use the new Preference v14 Support library. To give the preferences a material style, I use the following style on my Activity:

<style name="PreferenceTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
    <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>

效果很好.我的问题是,当我在运行时添加新的首选项时,它们会使用旧主题膨胀.结果截图如下:

That works fine. My problem is that when I add new Preferences at runtime, they get inflated using an old theme. Here's a screenshot of the result:

如您所见,通过 XML 添加的第一个首选项具有新的 Material 样式,而其他首选项没有.

As you can see, the first preference, added via XML, has the new Material style, while the others don't.

您对如何解决问题有任何提示吗?

Do you have any hint on how to solve the problem?

编辑这是我用来在运行时添加首选项的代码示例:

EDIT Here's an example of code I use to add the Preference at Runtime:

import android.support.v7.preference.ListPreference;

for (...) {
        final ListPreference p = new ListPreference(getActivity());
        p.setTitle(name);
        p.setSummary(langname);
        p.setEntryValues(langEntryValues);
        p.setEntries(langDisplayValues);
        p.setDialogTitle(R.string.select_language);

        category.addPreference(p);
    }

PS:同样的行为发生在 android.support.v7.preference.Preference

PS: The same behavior occurs with android.support.v7.preference.Preference

推荐答案

您面临的问题与 Context 及其主题的工作方式有关.您的代码通过将 getActivity() 传递给构造函数来检索上下文,但是,这不是您想要的上下文.这是应用正确样式的解决方案:

The problem, you're facing, is related to Context and how its theming works. Your code retrieves a context by passing getActivity() to the constructor, however, this is not the context you want. Here's the solution that applies the correct styles:

final Context ctx = getPreferenceManager().getContext();

for (...) {
    final ListPreference p = new ListPreference(ctx);
    // [...]

    category.addPreference(p);
}

说明

这里是 PreferenceFragmentCompatonCreate(...) 方法:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    TypedValue tv = new TypedValue();
    this.getActivity().getTheme().resolveAttribute(attr.preferenceTheme, tv, true);
    int theme = tv.resourceId;
    if(theme <= 0) {
        throw new IllegalStateException("Must specify preferenceTheme in theme");
    } else {
        this.mStyledContext = new ContextThemeWrapper(this.getActivity(), theme);
        this.mPreferenceManager = new PreferenceManager(this.mStyledContext);
        // [...]

        this.onCreatePreferences(savedInstanceState, rootKey);
    }
}

重要的几行:

this.getActivity().getTheme().resolveAttribute(attr.preferenceTheme, tv, true);
int theme = tv.resourceId;

这里的 preferenceTheme 是从活动的主题中检索的.如果它存在(即 theme 不是 0),PFC (PreferenceFragmentCompat) 创建一个新的主题包装器,其中将包含样式信息:

Here the preferenceTheme is being retrieved from the Activity's theme. If it exists (i.e. theme is not 0), PFC (PreferenceFragmentCompat) creates a new theme wrapper which will contain the styling infos:

this.mStyledContext = new ContextThemeWrapper(this.getActivity(), theme);

使用这种样式化的上下文,PFC 现在可以创建 PreferenceManager:

Using this styled context, the PFC can now create the PreferenceManager:

this.mPreferenceManager = new PreferenceManager(this.mStyledContext);

这个 PFCroot 样式现在是 preferenceTheme,它包含所有不同的子样式(preferenceStyle> 例如).

This PFC's root style is now the preferenceTheme which contains all the different sub-styles (preferenceStyle for example).

您的解决方案的问题在于 Preference 类在构造函数传递的上下文中寻找 preferenceStyle 属性.但是,它仅在您的 preferenceTheme 中定义,而不是在 Activity 的主题中定义.

The problem with your solution is that the Preference class is looking for a preferenceStyle attribute in the contructor-passed context. However, it's only defined in your preferenceTheme, not in the Activity's theme.

这篇关于新的首选项支持库在运行时不正确的主题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆