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 is due to the textAllCaps
bug on Android versions prior to Oreo (API level 26). That Button
's default style sets that attribute to true
, which causes its text to be converted to all uppercase.
That conversion is done with the platform AllCapsTransformationMethod
class which, on Nougat 7.1 and below, treats everything as flat String
s, essentially stripping any formatting spans you may have set. The fix is to turn that attribute off and handle any necessary uppercase conversions yourself in code.
Snackbar
offers the snackbarButtonStyle
theme attribute as a means to style its action Button
, and we can create a simple <style>
to override textAllCaps
with false
. For example, here's the linked project's styles.xml
updated:
<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.