Je veux teinter les icônes de mon tabhost en utilisant xml, au lieu de le faire par programme (je n'ai pas pu le faire de toute façon) ... J'ai donc trouvé ce fil sur SO: Android imageview change teinte pour simuler le clic du bouton
Cela semble être une assez bonne solution, mais je n'ai pas pu l'adapter correctement dans mon projet ... J'ai fait les changements suivants:
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);
}
}
Je n'ai pas non plus pu référencer @drawable/selector.xml
à Android:tint
, donc je l'ai fait sur 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>
Mon sélecteur:
<?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>
Ma disposition des onglets:
<?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>
Aucune suggestion? Merci d'avance
[EDIT] J'obtenais un NumberFormatException
pour utiliser Android:tint
, quand la bonne était app:tint
(après avoir défini xmlns:app="http://schemas.Android.com/apk/res/com.myapp"
) ... mais maintenant je pense que j'utilise mal mon sélecteur, car les icônes sont toutes noires, peu importe l'état ... J'ai essayé de régler <drawable name="tab_icon_selector">@drawable/tab_icon_selector</drawable>
à partir de colors.xml, n'a pas fonctionné
[/MODIFIER]
En référence à ma solution sur https://stackoverflow.com/a/18724834/2136792 , il manque quelques éléments:
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 () doit être remplacé pour que la teinte soit mise à jour lorsque l'état de l'élément change.
Je ne suis pas sûr que référencer un dessinable à partir d'un dessinable puisse causer un problème, mais vous pouvez simplement déplacer votre selector.xml dans un dossier "/ res/color" pour le référencer avec "@ color/selector.xml" (aapt fusionne à la fois /res/values/colors.xml et le dossier/res/color).
Si vous êtes dans l'API 21+, vous pouvez le faire facilement en XML avec un sélecteur et teinte :
<?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>
J'ai implémenté cela en utilisant DrawableCompat
à partir de la bibliothèque Android support-v4).
Avec un ImageButton
régulier (qui sous-classe ImageView
, donc cette information s'applique également aux ImageView
s), en utilisant une icône noire de la collection d'icônes de matériaux :
<ImageButton
Android:id="@+id/button_add"
Android:src="@drawable/ic_add_black_36dp"
Android:background="?attr/selectableItemBackgroundBorderless"
Android:contentDescription="@string/title_add_item" />
Voici la méthode utilitaire que j'ai créée:
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);
}
Où res/color/button_colour.xml
Est un sélecteur qui change la couleur de l'icône du rouge au rouge semi-transparent lorsque le bouton est enfoncé:
<?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>
Une fois la ImageButton
gonflée dans la méthode onCreate()
de mon activité, je n'appelle la méthode d'assistance tintButton(...)
qu'une seule fois pour chaque bouton.
J'ai testé cela sur Android 4.1 (mes minSdkVersion
) et les appareils 5.0, mais DrawableCompat
devrait fonctionner à Android 1.6.
Avec la bibliothèque de support 22.1, nous pouvons utiliser DrawableCompat pour teinter le dessin, API niveau 4+
DrawableCompat.wrap (Drawable) et setTint (), setTintList () et setTintMode () fonctionneront juste: pas besoin de créer et de maintenir des drawables séparés uniquement pour prendre en charge plusieurs couleurs!
Je suis d'accord avec @Dreaming dans Code et je vais vous donner un exemple.
ic_up_small
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:color="@color/comment_count_selected_color" Android:state_selected="true" />
<item Android:color="@color/comment_count_text_color"/>
</selector>
layout/item_post_count_info.xml
<Android.support.v7.widget.AppCompatImageView
Android:id="@+id/post_upvote_icon"
Android:layout_width="14dp"
Android:layout_height="14dp"
Android:layout_marginLeft="17dp"
app:srcCompat="@drawable/ic_up_small"
app:tint="@color/post_up_color"/>
Attention: Nous devons utiliser app: tint au lieu de Android: tint .
Ma version de bibliothèque de support est 26.0.2.
app/build.gradle
implementation 'com.Android.support:appcompat-v7:26.0.2'
implementation 'com.Android.support:support-core-utils:26.0.2'
implementation 'com.Android.support:support-annotations:26.0.2'
implementation 'com.Android.support:support-v4:26.0.2'
implementation 'com.Android.support:design:26.0.2'
Si nous utilisons Android: tint, il plantera et le journal sera comme ceci:
E/AndroidRuntime: FATAL EXCEPTION: main Android.view.InflateException: ligne de fichier XML binaire # 0: erreur de gonflement de la classe sur Android.view.LayoutInflater.createView (LayoutInflater.Java:613) sur Android.view.LayoutInflater.createViewFromTag (LayoutInflater. Java: 687) sur Android.view.LayoutInflater.rInflate (LayoutInflater.Java:746) sur Android.view.LayoutInflater.inflate (LayoutInflater.Java:489) sur Android.view.LayoutInflater.inflate (LayoutInflater.Java:396) sur com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.create (PostCountInfoViewHolder.Java:29) sur com.opera.six.viewholder.post.PostCountInfoViewHolder $ 1.create (PostCountInfoViewHolder.Java:25) sur com.opera.six. collection.CollectionAdapter.onCreateViewHolder (CollectionAdapter.Java:39) sur com.opera.six.collection.CollectionAdapter.onCreateViewHolder (CollectionAdapter.Java:19) sur Android.support.v7.widget.RecyclerView $ Adapter.createViewHolder (RecyclerView.Java: 6493) sur Android.support.v7.widget.RecyclerView $ Recycler.tryGetViewHolderForPosit ionByDeadline (RecyclerView.Java:5680) sur Android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.Java:5563) sur Android.support.v7.widget.RecyclerView $ Recycler.getViewForPosition (RecyclerView.Java:5559) sur Android.support.v7.widget.LinearLayoutManager $ LayoutState.next (LinearLayoutManager.Java:2229) sur Android.support.v7.widget.LinearLayoutManager.layoutChunk (LinearLayoutManager.Java:1556) sur Android.support.v7.widget.Lin .fill (LinearLayoutManager.Java:1516) sur Android.support.v7.widget.LinearLayoutManager.onLayoutChildren (LinearLayoutManager.Java:608) sur Android.support.v7.widget.RecyclerView.dispatchLayoutStep2 (RecyclerView.Java:93: Android). support.v7.widget.RecyclerView.dispatchLayout (RecyclerView.Java:3410) sur Android.support.v7.widget.RecyclerView.onLayout (RecyclerView.Java:3962) sur Android.view.View.layout (View.Java:13754) à Android.view.ViewGroup.layout (ViewGroup.Java:4364) à Android.support.v4.widget.SwipeRefreshLayout.onLayout (SwipeR efreshLayout.Java:610) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.support.design.widget.HeaderScrollingViewBehavior.layoutChild (HeaderScrollingViewBe .Java: 132) sur Android.support.design.widget.ViewOffsetBehavior.onLayoutChild (ViewOffsetBehavior.Java:42) sur Android.support.design.widget.AppBarLayout $ ScrollingViewBehavior.onLayoutChild (AppBarLayout.Java.support). design.widget.CoordinatorLayout.onLayout (CoordinatorLayout.Java:869) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.support.v4 .view.ViewPager.onLayout (ViewPager.Java:1767) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.widget.LinearLayout. setChildFrame (LinearLayout.Java:1649) sur Android.widget.LinearLayout.layoutVertical (LinearLayout.Java:1507) sur Android.widget.LinearLayout.onLayout (LinearLayout.Java:1420) sur Android. view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.widget.FrameLayout.onLayout (FrameLayout.Java:448) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.widget.FrameLayout.onLayout (FrameLayout.Java:448) sur Android.view.View.layout (View.Java: 13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.widget.LinearLayout.setChildFrame (LinearLayout.Java:1649) sur Android.widget.LinearLayout.layoutVertical (LinearLayout.Java:1507) sur Android. widget.LinearLayout.onLayout (LinearLayout.Java:1420) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.widget.FrameLayout.onLayout (FrameLayout.Java:448) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGroup.layout (ViewGroup.Java:4364) sur Android.widget.FrameLayout.onLayout (FrameLayout.Java: 448) sur Android.view.View.layout (View.Java:13754) sur Android.view.ViewGrou p.layout (Vi
Avec la bibliothèque de support AppCompat actuelle, vous pouvez utiliser app:tint
on ImageView
tag qui sera gonflé comme AppCompatImageView
et gérera le changement d'état correctement.
Dans AppCompatImageView
, vous pouvez voir que mImageHelper
est notifié du changement d'état:
@Override
protected void drawableStateChanged() {
super.drawableStateChanged();
if (mBackgroundTintHelper != null) {
mBackgroundTintHelper.applySupportBackgroundTint();
}
if (mImageHelper != null) {
mImageHelper.applySupportImageTint();
}
}
Android Studio donne actuellement un avertissement à ce sujet, mais vous pouvez le supprimer en toute sécurité.