【问题标题】:Apply tint to PreferenceActivity widgets with AppCompat v21使用 AppCompat v21 将色调应用于 PreferenceActivity 小部件
【发布时间】:2014-10-20 13:13:08
【问题描述】:

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

普通布局中的单选按钮,有色:

CheckboxPreference 中的复选框,未着色:

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

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

【问题讨论】:

  • 我也遇到了小部件着色和 CheckBox 小部件。我在 ActionBarActivity 布局中使用 CheckBox 控件,但它没有着色。我得到的只是默认的黑色矩形。无赖。
  • 此外,官方已经声明这是按预期工作的(见最后的常见问题解答)android-developers.blogspot.it/2014/10/…
  • 我在我的偏好活动中使用ActionBarActivity,并且色彩工作在复选框上。但是在ListPreference 中,复选框没有着色,只有在单击之后...

标签: android android-preferences android-appcompat material-design tint


【解决方案1】:

编辑:从 AppCompat 22.1 开始,任何活动都可以使用 AppCompatDelegate 进行主题化。着色视图类的名称也从 v7.internal.widget.TintXYZ 更改为 v7.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;
    }
}

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

请参阅ActionBarActivity.javaActionBarActivityDelegateBase.java 获取原始代码。

【讨论】:

    【解决方案2】:

    我知道这个问题有点老了,但我想留下一个解决方案来解决你遇到的这个问题。 首先,我想说PreferenceActivity 是蜂窝时代的遗迹,所以不要指望 Google 在这个非常古老的 Activity 子集中为您的小部件着色。
    您应该使用 PreferenceFragments 而不是 PreferenceActivity@,它将被包裹在 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 的容器

    结果:

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

    【讨论】:

    • 感谢您的回答,但该应用的 minSDK 为 10,所以即使我知道 PreferenceActivity 已被弃用,我也一定会使用它。
    • 我也在使用 ActionBarActivity 和 PreferenceFragment 的组合,它在通过资源添加时有效。但是,任何通过代码动态实例化的 CheckBoxPreference 仍然会产生一个黑色复选框。
    • @Q'' 这是正常的。支持的小部件将在充气期间被拦截并正确着色。如果您动态添加某些内容,则不会发生这种情况。作为参考,您可以收听this podcast (click) 特别是从 7:25 分钟开始的部分
    • @devrocca 在这种情况下,您应该使用两个不同的活动。 ;) 不需要正确支持这个超旧版本。
    • 复选框对我有用,但开关和列表首选项不起作用。
    【解决方案3】:

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

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

    drawable/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 光学正方形。

    【讨论】:

    • 我接受了这个,因为它与问题和 PreferenceActivity 用法有关。但是,由于该 Activity 已被弃用,因此最好的方法是使用 PreferenceFragment 作为 reVerse 的答案。
    • 我最终得到了你的解决方案,在我的情况下移动到 PreferenceFragment 太多了。
    【解决方案4】:

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

    imports 应该改为

    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);
    }
    

    【讨论】:

      【解决方案5】:

      如果您使用的是 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>
      

      不是(注意“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>
      

      这为我解决了这个问题。

      【讨论】:

      • 这是对的,但它不能与 PreferenceActivity 一起使用,因为正如开发人员所说,已弃用的 Activity 不使用能够自行应用颜色的 AppCompat 小部件。它确实可以与 PreferenceFragment 一起使用,这可能是您正在使用的。
      • 是的。我正在使用 PreferenceFragment。感谢您的澄清 devrocca。
      猜你喜欢
      • 1970-01-01
      • 2015-02-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多