Как использовать селектор для отображения изображения в андроиде

Я хочу подкрасить иконки tabhost с помощью xml вместо того, чтобы делать это программно (я так и не смог это сделать) … Итак, я нашел этот поток на SO: Android imageview изменил оттенок, чтобы имитировать нажатие кнопки

Это кажется довольно хорошим решением, но я не смог его правильно адаптировать в своем проекте … Я сделал следующие изменения:

public class TintableImageView extends ImageView { private ColorStateList tint; public TintableImageView(Context context) { super(context); } //this is the constructor that causes the exception public TintableImageView(Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs, 0); } public TintableImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs, defStyle); } //here, obtainStyledAttributes was asking for an array private void init(Context context, AttributeSet attrs, int defStyle) { TypedArray a = context.obtainStyledAttributes(attrs, new int[]{R.styleable.TintableImageView_tint}, defStyle, 0); tint = a.getColorStateList(R.styleable.TintableImageView_tint); a.recycle(); } @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (tint != null && tint.isStateful()) updateTintColor(); } public void setColorFilter(ColorStateList tint) { this.tint = tint; super.setColorFilter(tint.getColorForState(getDrawableState(), 0)); } private void updateTintColor() { int color = tint.getColorForState(getDrawableState(), 0); setColorFilter(color); } } 

Я также не смог ссылаться на @drawable/selector.xml на android:tint , поэтому я сделал это в colors.xml:

 <?xml version="1.0" encoding="utf-8"?> <resources> <color name="azulPadrao">#2e7cb4</color> <drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable> </resources> 

Мой селектор:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_selected="true" android:tint="#007AFF" /> <item android:state_focused="true" android:tint="#007AFF" /> <item android:state_pressed="true" android:tint="#007AFF" /> <item android:tint="#929292" /> </selector> 

Моя вкладка:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:id="@+id/TabLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center" android:background="@drawable/tab_bg_selector"> <com.myapp.TintableImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView" android:layout_gravity="center" android:tint="@drawable/tab_icon_selector"/> <TextView android:id="@+id/TabTextView" android:text="Text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@drawable/tab_text_selector" android:textSize="10dip" android:textStyle="bold" android:layout_marginTop="2dip"/> </LinearLayout> 

Какие-либо предложения? заранее спасибо

[EDIT] Я получал NumberFormatException для использования android:tint , когда правильное было app:tint (после установки xmlns:app="http://schemas.android.com/apk/res/com.myapp" ) .. Но теперь я думаю, что я использую свой селектор неправильно, потому что значки черны, независимо от состояния … Я пробовал настройку <drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable> Изнутри colors.xml, не работает

[/РЕДАКТИРОВАТЬ]

Solutions Collecting From Web of "Как использовать селектор для отображения изображения в андроиде"

Что касается моего решения на https://stackoverflow.com/a/18724834/2136792 , есть несколько вещей, которые вам не хватает:

TintableImageView.java

 @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (tint != null && tint.isStateful()) updateTintColor(); } public void setColorFilter(ColorStateList tint) { this.tint = tint; super.setColorFilter(tint.getColorForState(getDrawableState(), 0)); } private void updateTintColor() { int color = tint.getColorForState(getDrawableState(), 0); setColorFilter(color); } 

DrawableStateChanged () должен быть переопределен для изменения оттенка при изменении состояния элемента.

Я не уверен, что если ссылаться на drawable из drawable может вызвать проблему, но вы можете просто переместить ваш selector.xml в папку «/ res / color», чтобы ссылаться на нее с помощью «@ color / selector.xml» (aapt merges Оба /res/values/colors.xml и папка / res / color).

Если вы используете API 21+, вы можете легко это сделать в XML с селектором и оттенком :

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_activated="true"> <bitmap android:src="@drawable/ic_settings_grey" android:tint="@color/primary" /> </item> <item android:drawable="@drawable/ic_settings_grey"/> </selector> 

Я реализовал это с помощью DrawableCompat из библиотеки поддержки Android-v4.

С помощью обычного ImageButton (который подклассифицирует ImageView , поэтому эта информация также относится к ImageView s), используя черный значок из коллекции значков материалов :

 <ImageButton android:id="@+id/button_add" android:src="@drawable/ic_add_black_36dp" android:background="?attr/selectableItemBackgroundBorderless" android:contentDescription="@string/title_add_item" /> 

Это метод утилиты, который я создал:

 public static void tintButton(@NonNull ImageButton button) { ColorStateList colours = button.getResources() .getColorStateList(R.color.button_colour); Drawable d = DrawableCompat.wrap(button.getDrawable()); DrawableCompat.setTintList(d, colours); button.setImageDrawable(d); } 

Где res/color/button_colour.xml – это селектор, который меняет цвет значка от красного до полупрозрачного красного при нажатии кнопки:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="false" android:color="@color/red" /> <item android:color="@color/red_alpha_50pc" /> </selector> 

После того, как ImageButton был onCreate() методе onCreate() моей активности, я просто вызываю метод tintButton(...) для каждой кнопки.


Я тестировал это на устройствах Android 4.1 (my minSdkVersion ) и 5.0, но DrawableCompat должен вернуться к Android 1.6.

В библиотеке поддержки 22.1 мы можем использовать DrawableCompat для масштабирования, API уровня 4+

DrawableCompat.wrap (Drawable) и setTint (), setTintList () и setTintMode () будут работать: нет необходимости создавать и поддерживать отдельные чертежи только для поддержки нескольких цветов!

В текущей библиотеке поддержки AppCompat вы можете использовать тэг app:tint в теге ImageView который будет накачаться как AppCompatImageView и правильно обрабатывать состояние.

В AppCompatImageView вы можете видеть, что mImageHelper уведомляется об изменении состояния:

 @Override protected void drawableStateChanged() { super.drawableStateChanged(); if (mBackgroundTintHelper != null) { mBackgroundTintHelper.applySupportBackgroundTint(); } if (mImageHelper != null) { mImageHelper.applySupportImageTint(); } } 

Android Studio в настоящее время дает предупреждение об этом, но вы можете безопасно его подавить.