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 } }
公式がやってない辺りにちゃんと理由がありそうで、とても気になる。なんでだろう。