Search code examples
androidandroid-emulatorinvisiblekindle-firespannablestring

android TextView make invisible span on Kindle Fire


I want to have a portion of my TextView invisible. In detail, I present a math problem to the user:

9 * 9 = 81

and I want 81 to be invisible. As user types correct answer, I make digit "8" and then "1" visible.

I tried to use TextAppearanceSpan and ForegroundColorSpan with transparent color (both #00000000 and Color.TRANSPARENT) and they work perfectly for every device and emulator except KindleFire device and emulator.

On Kindle Fire, "81" appears colored in sort-of-dark-grey. It seems that rasterizer tries to make it invisible against some "sort-of-dark-grey" background, not against background (which looks like grid paper image) that I've set in the root LinearLayout of my Activity.

enter image description here

My question is: how can I make a portion of text in TextView invisible using neither TextAppearanceSpan nor ForegroundColorSpan? Does there exist another "span" that measures text correctly, but does not paint it?

Update

I've discovered that there exist some mysterous RasterizerSpan and MetricAffectingSpan, which could (judging by the title) help.

As I can see, the only meaning of RasterizerSpan is to set a Rasterizer to the TextPaint object:

    public void updateDrawState(TextPaint ds) {
    ds.setRasterizer(mRasterizer);
}

I found it promising: if I were able to set a kind of "void" rasterizer (that just does nothing), it would make this text invisible. Unfortunately

new RasterizerSpan(null); // (set mRasterizer to null)

did not help.

My another idea is to implement a custom ShaderSpan that would set a "void" shader:

    public void updateDrawState(TextPaint ds) {
    ds.setShader(myCustomVoidShader);
}

but I do not understand how to create a shader that produces "nothing".


Solution

  • See if overriding updateDrawState() on your ForegroundColorSpan and calling setXferMode() will work:

    public class TransparentSpan extends ForegroundColorSpan {
        private final PorterDuffXfermode MODE = new PorterDuffXfermode(PorterDuff.Mode.DST);
    
        public TransparentSpan(int color) {
            super(color);
        }
    
        @Override
        public void updateDrawState(TextPaint ds) {
            super.updateDrawState(ds);
            ds.setXfermode(MODE);
        }
    }
    

    Sorry, I didn't have a Kindle Fire to test with :)