TextView rendering is not consistent when laid on top of another TextView

Viewed 108

Due to animation requirements, I'm laying a TextView on top of another TextView and they have the same exact parameters and text. The TextView bounds match perfectly, as I already confirmed with layout inspector. Everything is similar, except that the text inside is not rendered in the same way:

Only one TextView Both TextViews

The first image only has one TextView. The second has both laid on top of each other. You can see that the rendering gets progressively worse.

The xml for both TextView is:

<TextView
    android:id="@+id/textBalance"
    style="@style/TextStyle.Header"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/size_4"
    android:ellipsize="end"
    android:maxLines="1"
    android:visibility="invisible"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@id/guidelineDashboardControls"
    tools:text="€ 3.526,04"/>

And:

<TextView
    android:id="@+id/textBalance"
    style="@style/TextStyle.Header"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/size_4"
    android:layout_marginTop="@dimen/size_11"
    android:ellipsize="end"
    android:maxLines="1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="€ 3.526,04"/>

And the style:

<style name="TextStyle.Header">
    <item name="android:textAppearance">@style/TextAppearance.Header</item>
</style>

<style name="TextAppearance.Header">
    <item name="android:fontFamily">@font/gloriola_medium</item>
    <item name="android:textSize">@dimen/text_header_size</item>
    <item name="android:textAllCaps">true</item>
    <item name="android:letterSpacing">0.0026</item> <!-- 0.1 / 38sp -->
    <item name="android:textColor">?colorPrimaryText</item>
</style>

It's not because of the font, as I already tried with the system ones. And it's also not because of size, allCaps or letterSpacing. I also tried some drawing cache parameters but without success.

2 Answers

Try to setBackground the TextView which is on top with the background color of the outer view. By this way, the TextView at bottom will be covered completely

I found the problem. I was actually trying to match it against another dummy TextView that was already being used as a spacer to align other content. But that TextView was invisible. So the text below was actually coming from the expanded title of a CollapsingToolbarLayout. It had the text appearance set to the same style, that's why it's so similar and I made the mistake of thinking it was from the dummy TextView.

But I also learned that the CollapsingToolbarLayout will only consider some parameters of the text appearance and ignore others. In the end the only way that I was able to have the text completely match was to use reflection to copy the attributes of the collapsing title paint object and apply them to the paint object of the dummy text views.

private fun CollapsingToolbarLayout.copyTitleStyle() {
    try {
        val helper = CollapsingToolbarLayout::class.java
            .getDeclaredField("collapsingTextHelper")
            .apply { isAccessible = true }
            .get(this) as CollapsingTextHelper

        val textPaint = CollapsingTextHelper::class.java
            .getDeclaredField("textPaint")
            .apply { isAccessible = true }
            .get(helper) as TextPaint

        textBalance.paint.set(textPaint)
    } catch (e: Exception) {
        Timber.w(e)
    }
}

This makes me cry, but solves the problem.

Related