运行时新的首选项支持库不正确的主题
New Preference support library incorrect theme at runtime
我正在尝试使用新的 Preference v14 支持库。为了给首选项一个 material 样式,我在我的 Activity 上使用了以下样式:
<style name="PreferenceTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
效果很好。我的问题是,当我在运行时添加新的首选项时,它们会使用旧主题膨胀。这是结果的屏幕截图:
如您所见,通过 XML 添加的第一个首选项具有新的 Material 样式,而其他首选项则没有。
你有什么解决问题的提示吗?
编辑
这是我用来在运行时添加首选项的代码示例:
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
会出现相同的行为
您面临的问题与 Context
及其主题的工作方式有关。您的代码通过将 getActivity()
传递给构造函数来检索上下文,但是,这不是您想要的上下文。这是应用正确样式的解决方案:
final Context ctx = getPreferenceManager().getContext();
for (...) {
final ListPreference p = new ListPreference(ctx);
// [...]
category.addPreference(p);
}
说明
这是 PreferenceFragmentCompat
的 onCreate(...)
方法:
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;
这里是从 Activity 的主题中检索 preferenceTheme
。如果它存在(即 theme
不是 0),PFC (PreferenceFragmentCompat
) 创建一个新的主题包装器,其中将包含样式信息:
this.mStyledContext = new ContextThemeWrapper(this.getActivity(), theme);
使用此样式上下文,PFC 现在可以创建 PreferenceManager
:
this.mPreferenceManager = new PreferenceManager(this.mStyledContext);
这个 PFC 的 root 样式现在是 preferenceTheme
,其中包含所有不同的子样式(preferenceStyle
例如)。
您的解决方案存在的问题是 Preference
class 正在构造函数传递的上下文中寻找 preferenceStyle
属性。但是,它仅在您的 preferenceTheme
中定义,而不是在 Activity 的主题中定义。
我正在尝试使用新的 Preference v14 支持库。为了给首选项一个 material 样式,我在我的 Activity 上使用了以下样式:
<style name="PreferenceTheme" parent="@style/Theme.AppCompat.Light.DarkActionBar">
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
效果很好。我的问题是,当我在运行时添加新的首选项时,它们会使用旧主题膨胀。这是结果的屏幕截图:
如您所见,通过 XML 添加的第一个首选项具有新的 Material 样式,而其他首选项则没有。
你有什么解决问题的提示吗?
编辑 这是我用来在运行时添加首选项的代码示例:
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
您面临的问题与 Context
及其主题的工作方式有关。您的代码通过将 getActivity()
传递给构造函数来检索上下文,但是,这不是您想要的上下文。这是应用正确样式的解决方案:
final Context ctx = getPreferenceManager().getContext();
for (...) {
final ListPreference p = new ListPreference(ctx);
// [...]
category.addPreference(p);
}
说明
这是 PreferenceFragmentCompat
的 onCreate(...)
方法:
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;
这里是从 Activity 的主题中检索 preferenceTheme
。如果它存在(即 theme
不是 0),PFC (PreferenceFragmentCompat
) 创建一个新的主题包装器,其中将包含样式信息:
this.mStyledContext = new ContextThemeWrapper(this.getActivity(), theme);
使用此样式上下文,PFC 现在可以创建 PreferenceManager
:
this.mPreferenceManager = new PreferenceManager(this.mStyledContext);
这个 PFC 的 root 样式现在是 preferenceTheme
,其中包含所有不同的子样式(preferenceStyle
例如)。
您的解决方案存在的问题是 Preference
class 正在构造函数传递的上下文中寻找 preferenceStyle
属性。但是,它仅在您的 preferenceTheme
中定义,而不是在 Activity 的主题中定义。