2010-06-11 16 views
49

J'ai un ImageButton dans mon application et j'ai besoin de changer la teinte de l'image lorsque le bouton est pressed/focused. Je l'ensemble ImageButton pour obtenir son src à partir d'un fichier XML qui comme suit:Comment puis-je changer la teinte d'un ImageButton sur le focus/appuyez sur

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <!-- pressed --> 
    <item 
     android:state_pressed="true" 
     android:tint="@color/black" 
     android:drawable="@drawable/search" 
     /> 

    <!-- focused --> 
    <item 
     android:state_focused="true" 
     android:tint="@color/black" 
     android:drawable="@drawable/search" 
     /> 

    <!-- default --> 
    <item 
     android:tint="@null" 
     android:drawable="@drawable/search" 
     /> 

</selector> 

Cependant, la teinte est pas appliquée lorsque l'on appuie sur ImageButton ou concentré - l'image juste affiche normalement. La couleur noire est définie comme #000000 comme toujours. Des idées?

+4

Bonjour. Je me demandais si vous avez finalement trouvé une façon XML de résoudre ce problème. Merci d'avance. –

Répondre

70

Vous pouvez changer la teinte, assez facilement dans le code via:

ImageButton button = (ImageButton) this.findViewById(R.id.button_i_want_to_modify); 
button.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint 

Hope it helps.

JS

+8

Fonctionne. Mais je voudrais le faire via XML si possible (désolé Picky). –

+0

Vérifiez la réponse à http://stackoverflow.com/questions/19500039/how-to-use-selector-to-tint-imageview-in-android – asiby

+0

Ou utilisez la liaison de données. – ubuntudroid

-2

Comme vous avez défini le sélecteur pour le src de la ImageButton Android va AFAIK juste prendre le drawable parce que ce correspond au type de src. Donc, la teinte ne sera pas utilisée.

Néanmoins, j'ai eu un problème similaire: j'ai également essayé d'utiliser un sélecteur comme le vôtre mais pour la valeur android: tint de l'ImageButton au lieu de android: src. Bien sûr, j'ai omis les valeurs de teinte que vous avez dans votre sélecteur. Cela résoudrait également votre problème, car vous souhaitez utiliser le même dessin pour tous les états. Curieusement, j'obtiens une exception NumberFormatException indiquant à chaque fois que le système n'a pas pu analyser 'res/color/tint_selector.xml' (qui est en fait mon sélecteur) en entier. Pour être précis mon code ressemble à ceci:

Ceci est mon sélecteur, enregistré dans /res/color/tint_selector.xml:

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" 
     android:color="#D3D3D3"/> <!-- pressed --> 
    <item android:color="#ff000000"/> <!-- default --> 
</selector> 

Et c'est le ImageButton correspondant:

<ImageButton android:id="@+id/program_help" 
    android:layout_height="wrap_content" 
    android:layout_width="wrap_content" 
    android:src="@drawable/symbol" 
    android:tint="@color/tint_selector"> 
</ImageButton> 

Peut-être que cela vous aide un peu, même si cela ne fonctionne pas actuellement.

+0

Est-ce compatible avec les API inférieures à 21? – JHowzer

1

Ce que je fais est d'ajouter un bouton personnalisé qui a la fonction setColorFilter. Comme ça, je peux utiliser le nouveau bouton dans le fichier XML.

public class CustomButton extends Button { 

public CustomButton(Context context) { 
    super(context); 
} 

public CustomButton(Context context, AttributeSet attributes) { 
    super(context, attributes); 
}; 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    int maskedAction = event.getActionMasked(); 
    if (maskedAction == MotionEvent.ACTION_DOWN) 
     getBackground().setColorFilter(Color.argb(150, 155, 155, 155), PorterDuff.Mode.DST_IN); 
    else if (maskedAction == MotionEvent.ACTION_UP) 
     getBackground().setColorFilter(null); 
    return super.onTouchEvent(event); 
}} 

et pour la ImageButton

public class CustomImageButton extends ImageButton { 

public CustomImageButton(Context context) { 
    super(context); 
} 

public CustomImageButton(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    int maskedAction = event.getActionMasked(); 
    if (maskedAction == MotionEvent.ACTION_DOWN) 
     setColorFilter(Color.argb(150, 155, 155, 155), PorterDuff.Mode.DST_IN); 
    else if (maskedAction == MotionEvent.ACTION_UP) 
     setColorFilter(null); 
    return super.onTouchEvent(event); 
}} 
1

j'ai remarqué il y a quelques demandes ici pour les personnes qui veulent savoir comment faire en XML. C'est en fait assez simple. Ceci peut être accompli en utilisant un layer-list

drawable (drawable/some_button.xml) Votre bouton:

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" android:drawable="@drawable/some_button_highlighted" /> 
    <item android:drawable="@drawable/some_button_image" /> 
</selector> 

Et ceci est le drawable souligné (drawable/some_button_highlighted.xml)

<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:drawable="@drawable/some_button_image"/> 
    <item> 
     <shape> 
      <solid android:color="@color/highlighted_button_color" /> 
     </shape> 
    </item> 
</layer-list> 

maintenant vous pouvez l'utiliser dans n'importe quel autre xml:

... 
android:drawable="@drawable/some_button" 
... 

J'espère que ceci aide quelqu'un dans le futur.

+3

Cela dessine juste un carré solide sur le drawable, s'il y avait un moyen d'obtenir le deuxième calque à utiliser le calque précédent comme un masque alpha alors ce serait cool – darnmason

2
bt.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       switch (event.getAction()) { 
        case MotionEvent.ACTION_DOWN: 
         bt.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint 
         return true; // if you want to handle the touch event 
        case MotionEvent.ACTION_UP: 
         bt.clearColorFilter(); // White Tint 
         return true; // if you want to handle the touch event 
       } 
       return false; 
      } 
     }); 
5

Enfin j'ai trouver la solution pour l'API < 21:

Button more = (Button) findViewById(R.id.more); 
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
    more.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN); 
} else { 
    Drawable wrapDrawable = DrawableCompat.wrap(more.getBackground()); 
    DrawableCompat.setTint(wrapDrawable, color)); 
    more.setBackgroundDrawable(DrawableCompat.unwrap(wrapDrawable)); 
} 

ce que quelqu'un aide peut ne pas perdre 2 heures!

+0

si vous utilisez drawablecompat vous devriez être capable de l'utiliser sur versions d'API inférieures sans problème – dabluck

+0

J'utilisais un bouton normal avec une disposition XML personnalisée. DrawableCompat était le seul correctif jusqu'à aujourd'hui qui fonctionne sur pré-API 21. –

4

J'ai trouvé un moyen de le faire en XML (dans les API 21 et au moins).

<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item android:state_pressed="true" > 
     <bitmap 
      android:src="@drawable/search" 
      android:tint="@color/black" 
      /> 
    </item> 
    <item android:drawable="@drawable/search"/> 
</selector> 

En réglant la teinte sur le bitmap il est possible de réutiliser le même drawable en XML sans avoir à intercepter des touches ou sous-classe ImageView ou ImageButton.

Une fois le sélecteur créé, appliquez-le simplement en tant que src de ImageView ou ImageButton.

+0

Belle prise! veuillez noter que l'attribut tint sur l'élément bitmap avant API 21 ne fera rien -> https://code.google.com/p/android/issues/detail?id=78461 – Gomino

0

Vous pouvez définir la couleur (teinte) à partir de xml.

Set transparent (android:background="@null") pour background puis utilisez tint:

<ImageButton 
    android:layout_width="wrap_content" 
    android:layout_height="fill_parent" 
    android:tint="@color/Amber_200" 
    android:background="@null" 
    android:src="@drawable/back_selector" /> 
1

Voici comment il l'a fait en utilisant seulement xml. Dans votre dossier drawable créez un sélecteur. Par exemple: touch_selector.xml

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 

    <!-- State when a row is being pressed, but hasn't yet been activated (finger down) --> 
    <item android:state_pressed="true" android:color="@color/semi_slate" /> 

    <!-- When the view is "activated". In SINGLE_CHOICE_MODE, it flags the active row 
    of a ListView --> 
    <item android:state_activated="true" android:color="@color/semi_slate" /> 

    <!-- Default, "just hangin' out" state. --> 
    <item android:color="@android:color/transparent" /> 
</selector> 

À mon avis Image en xml je définir l'attribut android: teinte au drawable créé ci-dessus.

android:tint = "@drawable/touch_selector" 

Le code tout ressemblait à ceci:

<?xml version="1.0" encoding="utf-8"?> 
<ImageView xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/poster" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:adjustViewBounds="true" 
android:scaleType="centerCrop" 
android:tint="@drawable/touch_selector" /> 

Ceci est une solution universelle xml, de mettre sur une teinte ImageView sur la presse ou sur actif. Similaire peut être fait pour ImageButton