おでーぶでおでーぶ

いろいろ書く。いろいろ。

pre-Lolipop でも TextView に icon tint を書けたい

MaterialComponent 対応をしていて、menu iconなども全部 theme baseのカラーリングにリファクタリングしている。

その中に pre-Lolipop でも TextView のicondrawable にtintが効かないというものがあったので、以下の方法で対応した。

import android.content.Context
import android.os.Build
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.widget.TextViewCompat
import com.google.android.material.theme.MaterialComponentsViewInflater

class LayoutInflater : MaterialComponentsViewInflater() {

    // pre-L cannot apply tint color for text view drawable
    override fun createTextView(context: Context, attrs: AttributeSet?): AppCompatTextView {
        val textView = super.createTextView(context, attrs)

        // throwable をsuppress するだけのtry-catchを別で書いている
        trySafely {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                val drawables = textView.compoundDrawables

                if (drawables.all { it == null }) {
                    return textView
                }

                val ta = context.theme.obtainStyledAttributes(R.styleable.AppTheme)

                val color = ta.getColor(R.styleable.AppTheme_drawableIconColor, -1)

                ta.recycle()

                if (color == -1) {
                    return textView
                }

                val newDrawables = drawables.map {
                    if (it != null) {
                        val wrapped = DrawableCompat.wrap(it)

                        DrawableCompat.setTint(wrapped, color)

                        wrapped.setBounds(0, 0, wrapped.intrinsicWidth, wrapped.intrinsicHeight)
                        wrapped
                    } else {
                        null
                    }
                }

                TextViewCompat.setCompoundDrawablesRelative(
                    textView,
                    newDrawables[0],
                    newDrawables[1],
                    newDrawables[2],
                    newDrawables[3]
                )
            }
        }

        return textView
    }
}

公式がやってない辺りにちゃんと理由がありそうで、とても気になる。なんでだろう。