16

我在 PreferenceActivity 和 v21 支持库中的 AppCompat 主题中使用 CheckboxPreference。如您所知,使用这个最新的库小部件,如复选框、编辑文本、单选按钮等,都使用主题中定义的辅助颜色进行着色。在首选项屏幕中,文本是我的主题指定的正确颜色,但复选框和编辑文本不是。似乎当 CheckboxPreference 实例创建小部件时,它并没有将我的主题应用于它。

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

截图 1

CheckboxPreference 中的复选框,未着色:

截图 2

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

更新:不应用着色,因为 PreferenceActivity 扩展了框架 Activity。在工作案例中,我使用了支持库中的 ActionBarActivity。现在的问题是:怎么会?

4

5 回答 5

10

编辑:从 AppCompat 22.1 开始,任何活动都可以使用AppCompatDelegate进行主题化。着色视图类的名称也从 更改v7.internal.widget.TintXYZv7.widget.AppCompatXYZ。以下答案适用于 AppCompat 22.0 及更早版本。


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

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,这允许 Activity 覆盖哪些类被实例化确保活动主题设置为 Theme.AppCompat。(或后代)在清单中。

原始代码参见ActionBarActivity.javaActionBarActivityDelegateBase.java

于 2014-12-30T21:51:44.013 回答
6

我知道这个问题有点老了,但我想留下一个解决方案来克服你遇到的这个问题。首先我想说这PreferenceActivity是蜂窝时代的遗迹,所以不要指望谷歌会在这个非常古老的活动子集中为你的小部件着色。
而不是你应该使用的 PreferenceActivity PreferenceFragments,它将被包裹在一个ActivityActionbarActivity如果你希望你的小部件被着色,最好是一个)。

遵循一个非常基本的代码示例,您的设置活动应该是什么样子。

例子

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 的容器

结果:

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

如您所见,您的小部件将根据colorAccent您设置的颜色正确着色。
有关developer.android.com 上的 PreferenceFragments 的更多信息(点击)

于 2014-12-13T09:28:41.297 回答
2

到目前为止,我自己的(悲伤的)解决方法是从头开始创建我自己的复选框可绘制对象,使用复选框应该首先着色的颜色。

在样式.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" andcheckbox_off` 是选定和未选定状态的 PNG 可绘制对象,显然每个屏幕密度都有一个。如果您介意尺寸一致性,可绘制对象的基线 (MDPI) 尺寸应为 32px 完整资源和 18px 光学正方形。

于 2014-10-20T18:53:05.437 回答
2

Tamás Szincsák 给出的解决方案效果很好,但如果使用 appcompat-v7:22.1.1,它应该更新,如下所示:

进口应改为

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);
}
于 2015-04-28T12:24:58.047 回答
1

如果您使用的是 AppCompat,请使用 style.xml 文件中的应用程序兼容项。

例如,使用:

<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>

不是(注意“机器人:”):

<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>

这为我解决了这个问题。

于 2015-03-06T22:15:11.873 回答