I want to show a Snackbar
and use an image instead of text for the action.
I use the following code:
val imageSpan = ImageSpan(this, R.drawable.star)
val builder = SpannableStringBuilder(" ")
builder.setSpan(
imageSpan,
0,
1,
SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE
)
Snackbar.make(findViewById(R.id.container), "Hello Snackbar", Snackbar.LENGTH_INDEFINITE)
.setAction(builder) {}.show()
drawable_star
being a vector graphic asset, but the same happens with a png
.
On an Android device lvl 26 and above this yields:
as expected, whereas on device lvl 25 the image is not visible:
Does someone know the reason for this and if there a workaround?
PS: You can check out my test project here: https://github.com/fmweigl/SpannableTest
That's due to the textAllCaps
bug on versions prior to Oreo. That Button
's default style will have that attribute set to true
, which simply causes the Button
's text to be converted to all uppercase. That conversion is done with the platform AllCapsTransformationMethod
class, which, on Nougat 7.1 and below, would treat everything as flat String
s, essentially stripping any formatting spans you've set.
The fix is to turn that attribute off, and handle any uppercase conversion you might need yourself, in code. Snackbar
offers the snackbarButtonStyle
attribute as a means to style the action Button
, and we can create a simple style to modify that value. For example, from your styles.xml
:
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="snackbarButtonStyle">@style/NoCapsButton</item>>
</style>
<style name="NoCapsButton" parent="Widget.AppCompat.Button">
<item name="textAllCaps">false</item>
</style>
(If you're using a Material Components theme, the parent
for NoCapsButton
should instead be Widget.MaterialComponents.Button.TextButton.Snackbar
.)
In this specific case, that's all you need to do, since there's no text to convert.