默认样式资源pre API Level 21

时间:2017-03-09 21:39:30

标签: android android-custom-view android-styles android-viewgroup android-api-levels

我希望创建一个在库中使用的自定义ViewGroup;其中包含一些ImageButton个对象。我希望每个ImageButton能够应用一种风格;但除了将属性资源应用于defStyleAttr参数之外,我无法弄清楚如何以编程方式应用样式;像这样:

mImageButton = new ImageButton(
        getContext(),                    // context
        null,                            // attrs
        R.attr.customImageButtonStyle);  // defStyleAttr

这个问题是,改变每个ImageButton样式的唯一方法是在父主题中对该属性应用样式。但我希望能够设置默认样式,而无需为使用此库的每个项目手动设置此属性。

有一个参数完全符合我的要求; defStyleRes,可以这样使用:

mImageButton = new ImageButton(
        getContext(),                    // context
        null,                            // attrs
        R.attr.customImageButtonStyle,   // defStyleAttr
        R.style.customImageButtonStyle); // defStyleRes

此参数仅在API级别21及更高版本中可用,但我的项目目标是API级别16及更高级别。那么如何在不访问此参数的情况下设置defStyleRes或应用默认样式?

我根据@EugenPechanec的建议使用ContextThemeWrapper来应用我的风格,这似乎运作良好,但每个ImageButton现在都有默认的ImageButton背景,即使我的风格适用<item name="android:background">@null</item>

这是我正在使用的风格:

<style name="Widget.Custom.Icon" parent="android:Widget">
    <item name="android:background">@null</item>
    <item name="android:minWidth">56dp</item>
    <item name="android:minHeight">48dp</item>
    <item name="android:tint">@color/selector_light</item>
</style>

这就是我应用它的方式:

ContextThemeWrapper wrapper = new ContextThemeWrapper(getContext(), R.style.Widget_Custom_Icon);
mImageButton = new AppCompatImageButton(wrapper);

左边是我得到的,右边是我想要的样子:

enter image description here enter image description here

1 个答案:

答案 0 :(得分:1)

defStyleAttr用于从主题属性中解析默认小部件样式。

示例:AppCompatCheckBox要求R.attr.checkBoxStyle。您的主题定义了<item name="checkBoxStyle">@style/Widget.AppCompat.CheckBox</item>

如果您的主题中未定义该属性,则小部件将拾取其defStyleRes,例如R.style.Widget_AppCompat_CheckBox

请注意,这些不是窗口小部件使用的实际值。

我还没有看到在框架之外使用的defStyleRes 构造函数参数。但是,在向TypedArray询问资源时,会使用所有这些参数(加上默认值)。

如何实际解决问题

所以四个参数构造函数并不适用于所有平台。您需要找到一种以默认样式提供的方式。考虑一下您想要应用的风格:

<style name="MyImageButtonStyle" parent=""> ... </style>

您需要一种方法将其转换为defStyleAttr参数。在主题叠加上定义默认样式:

<style name="MyImageButtonThemeOverlay" parent="">
    <!-- AppCompat widgets don't use the android: prefix. -->
    <item name="imageButtonStyle">@style/MyImageButtonStyle</item>
</style>

现在,您可以使用此主题叠加层创建ImageButton

// When creating manually you have to include the AppCompat prefix.
mImageButton = new AppCompatImageButton(
    new ContextThemeWrapper(getContext(), R.style.MyImageButtonThemeOverlay)
);

您无需指定任何其他参数,因为AppCompatImageButton默认会提取R.attr.imageButtonStyle

如果看起来很糟糕,您可以随时从指定style="@style/MyImageButtonStyle"属性的XML中扩充自定义视图层次结构或单个窗口小部件。