Default Style Resource pre API Level 21

佐手、 提交于 2019-12-12 04:23:37

问题


I am looking to create a custom ViewGroup to be used in a library; which contains a few ImageButton objects. I would like to be able to apply a style each ImageButton; but I cannot figure out how to apply a style programmatically other than by applying a attribute resource to the defStyleAttr parameter; like so:

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

The issue with this is that the only way to change the style of each ImageButton would be by applying a style to this attribute in a parent theme. But I would like to be able to set a default style, without having to manually set this attribute for each project that uses this library.

There is a parameter that does exactly what I am looking for; defStyleRes, which can be used like so:

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

This parameter is only available at API Level 21 and above, but my projects target API Level 16 and above. So how can I set the defStyleRes, or apply a default style, without access to this parameter?


I applied my style using a ContextThemeWrapper, as suggested by @EugenPechanec, which seems to work well, but each ImageButton now has the default ImageButton background, even though my style applies <item name="android:background">@null</item>.

Here is the style I am using:

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

And this is how I am applying it:

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

On the left is what I am getting, and on the right is what I would like it to look like:


回答1:


defStyleAttr is for resolving default widget style from theme attribute.

Example: AppCompatCheckBox asks for R.attr.checkBoxStyle. Your theme defines <item name="checkBoxStyle">@style/Widget.AppCompat.CheckBox</item>.

If that attribute is not defined in your theme the widget would pickup its defStyleRes e.g. R.style.Widget_AppCompat_CheckBox.

Note that these are not actual values used by the widget.

I have not seen defStyleRes constructor parameter used outside of the framework. All of these parameters (plus defaults) are however used when asking TypedArray for resources.

How to actually solve your problem

So the four parameter constructor is not available on all platforms. You need to find a way to feed in your default style. Consider a style you'd like to apply:

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

You need a way to convert it to a defStyleAttr parameter. Define the default style on a theme overlay:

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

Now you can create your ImageButton using this theme overlay:

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

You don't need to specify any other parameters as AppCompatImageButton will pickup R.attr.imageButtonStyle by default.


If that looks hacky you can always inflate your custom view hierarchy or individual widgets from XML where you specified the style="@style/MyImageButtonStyle" attribute.



来源:https://stackoverflow.com/questions/42705945/default-style-resource-pre-api-level-21

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!