使用AppCompat v21将色调应用于PreferenceActivity小部件

我在PreferenceActivity中使用CheckboxPreference,在v21支持库中使用AppCompat主题。 就像你已经知道的那样,使用这个最新的图库小部件,比如checkbox,editTexts,单选button等都是用主题中定义的第二种颜色着色的。 在首选项屏幕中,文本的颜色是由我的主题指定的,但checkbox和edittext不是。 看来,当CheckboxPreference实例创build小部件时,它不会将我的主题应用到它。

正常布局中的单选button,有色:

截图1 http://img.androidcookie.com/android/2qv9stj.png

CheckboxPreference中的checkbox没有着色:

截图2 http://img.androidcookie.com/android/91bcly.png

我正在使用作为父主题Theme.AppCompat.Light.NoActionBar 。 这发生在一个小部件的Preference的每个子类,就像EditTextPreference说的那样,其中EditText有一个黑底线,而不是有色线。 如何将偏色应用于偏好子类显示的小部件?

更新 :设色不适用,因为PreferenceActivity扩展框架活动。 在工作案例中,我使用支持库中的ActionBarActivity。 现在的问题是:怎么回事?

Solutions Collecting From Web of "使用AppCompat v21将色调应用于PreferenceActivity小部件"

编辑 :从AppCompat 22.1开始,任何活动都可以使用AppCompatDelegate来实现 。 有色视图类的名称也从v7.internal.widget.TintXYZ更改为v7.widget.AppCompatXYZ 。 下面的答案适用于AppCompat 22.0及更高版本。


我也遇到过这个问题,并通过简单地从ActionBarActivity复制与部件着色有关的代码来解决它。 这个解决scheme的一个缺点是它依赖于内部的类可能会改变或将来变得不可用。

 import android.support.v7.internal.widget.TintCheckBox; import android.support.v7.internal.widget.TintCheckedTextView; import android.support.v7.internal.widget.TintEditText; import android.support.v7.internal.widget.TintRadioButton; import android.support.v7.internal.widget.TintSpinner; public class MyActivity extends PreferenceActivity { @Override public View onCreateView(String name, Context context, AttributeSet attrs) { // Allow super to try and create a view first final View result = super.onCreateView(name, context, attrs); if (result != null) { return result; } if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { // If we're running pre-L, we need to 'inject' our tint aware Views in place of the // standard framework versions switch (name) { case "EditText": return new TintEditText(this, attrs); case "Spinner": return new TintSpinner(this, attrs); case "CheckBox": return new TintCheckBox(this, attrs); case "RadioButton": return new TintRadioButton(this, attrs); case "CheckedTextView": return new TintCheckedTextView(this, attrs); } } return null; } } 

这是可行的,因为由LayoutInflater服务调用的onCreateView对于从布局资源膨胀的每个视图来说都是允许活动覆盖哪些类被实例化的。 确保活动主题设置为Theme.AppCompat。 (或后代)在清单。

有关原始代码,请参阅ActionBarActivity.java和ActionBarActivityDelegateBase.java 。

我知道这个问题有点古怪,但我想留下一个解决scheme来解决你遇到的这个问题。 首先,我想说的是, PreferenceActivity是一个预蜂窝时代的遗迹,所以不要指望Google在这个真正旧的Activity子集中调色你的Widgets。
而不是PreferenceActivity你应该使用PreferenceFragments将被包裹在一个Activity (最好是一个ActionbarActivity如果你想你的小部件被着色)。

遵循一个非常基本的代码示例,您的设置活动应该如何。

 public class MySettings extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.settings_activity); getFragmentManager().beginTransaction() .replace(R.id.container, new MyPreferenceFragment()).commit(); } public static class MyPreferenceFragment extends PreferenceFragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.preferences_file); } } } 

注意: 在这个例子中,我使用了一个FrameLayout作为PreferenceFragments的容器

结果:

示例在首选项中显示有色小部件

所以你可以看到你的Widget会根据你设定的颜色来正确着色。
更多关于developer.android.com上的 PreferenceFragments (点击) 。

到目前为止,我自己的(悲伤)解决方法是从头开始创build自己的checkboxdrawables,使用checkbox应该首先着色的颜色。

在styles.xml中:

 <?xml version="1.0" encoding="utf-8"?> <style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar"> ... <!-- edit the checkbox appearance --> <item name="android:listChoiceIndicatorMultiple">@drawable/my_checkbox</item> ... </style> 

绘制/ my_checkbox.xml:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_checked="true" android:drawable="@drawable/checkbox_on" /> <item android:drawable="@drawable/checkbox_off" /> </selector> 

checkbox_on" and checkbox_off“是所选和未select状态的PNG可绘图,对于每个屏幕密度显然是一个,如果介意尺寸一致性,绘图的基准(MDPI)尺寸应该是32px全资产和18px光平方。

由TamásSzincsák给出的解决scheme效果很好,但是如果使用appcompat-v7:22.1.1,应该更新它,如下所示:

import应该改成

 import android.support.v7.widget.AppCompatCheckBox; import android.support.v7.widget.AppCompatCheckedTextView; import android.support.v7.widget.AppCompatEditText; import android.support.v7.widget.AppCompatRadioButton; import android.support.v7.widget.AppCompatSpinner; 

并分别开关应该是

 switch (name) { case "EditText": return new AppCompatEditText(this, attrs); case "Spinner": return new AppCompatSpinner(this, attrs); case "CheckBox": return new AppCompatCheckBox(this, attrs); case "RadioButton": return new AppCompatRadioButton(this, attrs); case "CheckedTextView": return new AppCompatCheckedTextView(this, attrs); } 

如果您正在使用AppCompat,则使用style.xml文件中的应用程序compat项目。

例如,使用:

 <style name="AppTheme" parent="Theme.AppCompat.Light"> <item name="colorPrimary">@color/primary</item> <item name="colorPrimaryDark">@color/primary_dark</item> <item name="colorAccent">@color/accent</item> </style> 

NOT(注意“android:”):

 <style name="AppTheme" parent="Theme.AppCompat.Light"> <item name="android:colorPrimary">@color/primary</item> <item name="android:colorPrimaryDark">@color/primary_dark</item> <item name="android:colorAccent">@color/accent</item> </style> 

这为我解决了这个问题。