Оттенок TextView на AppCompat
Я сделал несколько флажков и переключателей с текстовыми представлениями, но они не окрашены перед леденцом на палочке.
Мои текстовые представления расширяются AppCompatCheckedTextView
, в стиле:
<style name="CheckBoxStyle" parent="android:Widget.TextView">
<item name="android:textAppearance">?android:attr/textAppearance</item>
<item name="android:drawableRight">?android:attr/listChoiceIndicatorMultiple</item>
<item name="android:drawableEnd">?android:attr/listChoiceIndicatorMultiple</item>
<item name="android:clickable">true</item>
<item name="android:background">?attr/selectableItemBackground</item>
<item name="android:gravity">center_vertical</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
</style>
и мой акцент определен в моей теме:
<style name="AppTheme.Platform.NoActionBar" parent="Theme.AppCompat.NoActionBar">
<item name="android:selectableItemBackground">@drawable/press_overlay_dark</item>
<item name="android:borderlessButtonStyle">@style/BorderlessButton</item>
<item name="android:colorAccent">@color/color_accent</item>
<item name="colorAccent">@color/color_accent</item>
</style>
Я строю против v21, с минимумом v16 и использую AppCompat v7-22.1.1. Моя деятельность расширяет AppCompatActivity
5 ответов
Глядя на источник для AppCompatCheckedTextView
Я наконец понял это. Это только подкрашивает checkMark
, Так как это происходит из CheckedTextView
который вытекает из TextView
, drawableRight
только тонируется на леденце. Глядя на источник для AppCompatTextView
, он обеспечивает только обратную совместимость textAllCaps
, Так что AFAIK, нет встроенного способа подкрасить drawableRight
и тому подобное перед леденцом на палочке. Если вы хотите более настраиваемое решение, вам может понадобиться разместить свои чертежи в макете.
Обновленный стиль:
<style name="CheckBoxStyle" parent="android:Widget.TextView">
<item name="android:textAppearance">@style/TextAppearance.AppCompat</item>
<item name="android:checkMark">?android:attr/listChoiceIndicatorSingle</item>
<item name="android:clickable">true</item>
<item name="android:background">?attr/selectableItemBackground</item>
<item name="android:gravity">center_vertical</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
</style>
Для уровня API 23 >= android:drawableTint="@color/colorPrimary"
Для уровня Api <уровень Api 23:
private void setTextViewDrawableColor(TextView textView, int color) {
for (Drawable drawable : textView.getCompoundDrawables()) {
if (drawable != null) {
drawable.setColorFilter(new PorterDuffColorFilter(getColor(color), PorterDuff.Mode.SRC_IN));
}
}
}
Для API 23 и выше, просто установите его в макете: android:drawableTint="@color/custom_color"
Если вам нужна обратная совместимость, вам нужно будет установить ее программно. В Kotlin вы можете создать функцию расширения, например:
fun TextView.setDrawableColor(@ColorRes color: Int) {
compoundDrawables.filterNotNull().forEach {
it.colorFilter = PorterDuffColorFilter(getColor(context, color), PorterDuff.Mode.SRC_IN)
}
}
И используйте это как: textView.setDrawableColor(R.color.custom_color)
Обратите внимание, что filterNotNull()
здесь очень важно, поскольку список элементов для рисования, скорее всего, будет иметь некоторые нулевые значения (для всех элементов рисования в TextView, которые не были установлены).
Не прямой ответ на решение. Однако, если вы используете привязку данных и хотите добавить оттенок для рисования. Проверьте следующий пример: протестировано на последних версиях, но также должно работать на Api <=21
@JvmStatic
@BindingAdapter(value = ["app:drawableStart", "app:drawableStartTint"], requireAll = true)
fun setDrawableStartTint(textView: TextView, @DrawableRes drawable: Drawable, @ColorInt color: Int) {
val mutatedDrawable = drawable.mutate()
mutatedDrawable.setColorFilter(color, PorterDuff.Mode.MULTIPLY)
textView.setCompoundDrawablesWithIntrinsicBounds(mutatedDrawable, null, null, null)
}
Использование:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
app:drawableStart="@{@drawable/ic_demo}"
app:drawableStartTint="@{@color/color_demo_tint}"
/>
Вот обратно совместимый TextView.
Использование:
<com.github.mrezanasirloo.TextViewCompatTint
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_comment_black_14dp"
app:drawableTint="@color/colorPrimary"
tools:text="28"
/>
Тонировка виджета в AppCompat работает путем перехвата любой разметки макета и вставки на его место специальной версии виджета, учитывающей оттенки. Если у вас есть собственная настраиваемая версия виджета, которая в вашем случае - проверенный текстовый вид, тонировка не будет работать
От блога разработчиков под тонировку виджета
http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html
При работе на устройствах с Android 5.0 все виджеты окрашиваются с использованием атрибутов цветовой темы, о которых мы только что говорили. В Lollipop есть две основные функции, которые позволяют это: рисовать подкрашиванием и ссылаться на атрибуты темы (в форме? Attr / foo) в отрисовках.
AppCompat обеспечивает аналогичное поведение в более ранних версиях Android для подмножества виджетов пользовательского интерфейса:
Все, что предусмотрено панелью инструментов AppCompat (режимы действий и т. Д.)
Редактировать текст
волчок
CheckBox
Переключатель
Переключатель (используйте новый android.support.v7.widget.SwitchCompat)
CheckedTextView
Вам не нужно делать ничего особенного, чтобы заставить их работать, просто используйте эти элементы управления в ваших макетах, как обычно, и AppCompat сделает все остальное (с некоторыми оговорками; см. FAQ ниже).
У меня проблема с оттенком. AppCompatTextView не имеет эффекта оттенка при работе на SDK ниже 21. Мое решение - установить цвет оттенка через Java. Пример ниже работает.
XML
<android.support.v7.widget.AppCompatTextView
android:layout_width="50dp"
android:layout_height="20dp"
android:id="@+id/tvInfor2"
android:background="@drawable/btn_style_black_border"
android:gravity="center"
android:backgroundTint="@color/colorPrimary"/>
Джава
int currentapiVersion = android.os.Build.VERSION.SDK_INT;
if (currentapiVersion <= 21){
tvInfor2.setSupportBackgroundTintList(getResources().getColorStateList(R.color.colorPrimary));
}
В котлин:
fun TextView.setDrawableTintColor(colorRes: Int) {
for (drawable in this.compoundDrawablesRelative) {
drawable?.colorFilter = PorterDuffColorFilter(getColor(context, colorRes), PorterDuff.Mode.SRC_IN)
}
}
Использование:
myTextView.setDrawableTintColor(R.color.colorPrimary)
Упрощая верхний ответ, это будет расширение в Котлине (но я не проверял):
fun TextView.setDrawableColor(@ColorRes color: Int) {
val colorFilter = PorterDuffColorFilter(getColor(context, color), PorterDuff.Mode.SRC_IN)
compoundDrawables.filterNotNull().forEach {
it.colorFilter = colorFilter
}
}
Среди всех решений, которые у меня не работают, я создал следующие:
JAVA: совместимый Api < 23
private void setTextViewDrawableColor(@RecentlyNonNull TextView textView,@ColorRes int color) {
for (Drawable drawable : textView.getCompoundDrawablesRelative()) {
if (drawable != null) {
drawable.setColorFilter(new PorterDuffColorFilter(ContextCompat.getColor(textView.getContext(),color), PorterDuff.Mode.SRC_IN));
}
}
}
Использовать
setTextViewDrawableColor(textView1,R.color.AccentColor)
КОТЛИН
private fun setTextViewDrawableColor(@NonNull textView: TextView, @ColorRes color: Int) {
for (drawable in textView.compoundDrawablesRelative) {
if (drawable != null) {
drawable.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(textView.context, color), PorterDuff.Mode.SRC_IN)
}
}
}
Использовать
setTextViewDrawableColor(textView1,R.color.AccentColor)
КОТЛИНСКОЕ РАСШИРЕНИЕ
fun TextView.setDrawableColor(@ColorRes color: Int) {
compoundDrawablesRelative.filterNotNull().forEach {
it.colorFilter = PorterDuffColorFilter(ContextCompat.getColor(this.context, color), PorterDuff.Mode.SRC_IN)
}
}
использовать
textView1.setDrawableColor(R.color.colorAccent)
ТОЛЬКО XML API => 23
android:backgroundTintMode="src_in"
android:drawableTint="FF0000"