I have an ImageButton
in my app and I need to change the tint of the image when the button is pressed/focused
. I have the ImageButton
set to get its src
from an XML file which as follows:
<?xml version="1.0开发者_JAVA百科" 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>
However the tint isn't applied when the ImageButton
is pressed or focused - the image just displays as normal. The color black is defined as #000000
as always. Any ideas?
You can change the tint, quite easily in code via:
ImageButton button = (ImageButton) this.findViewById(R.id.button_i_want_to_modify);
button.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint
Here is how to do it using just xml. In your drawable folder create a selector. Eg: 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>
In my Image view in xml I set the android:tint attribute to the drawable created above.
android:tint = "@drawable/touch_selector"
The whole code looked like this:
<?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" />
This is an all xml solution, to put tint on an ImageView on press or on active. Similar can be done for ImageButton
Note that this only works for API level >= 21.
Finally I have found a solution for 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));
}
May this help someone not to lose 2 hours !
I found a way to do this in xml (in api 21 and up at least).
<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>
By setting the tint on the bitmap it's possible to reuse the same drawable in xml without having to intercept touches or subclass ImageView or ImageButton.
Once the selector has been created, just apply that as the src of the ImageView or ImageButton.
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;
}
});
What I'm doing is add a custom button that has the function setColorFilter.
Like this I can use the new button in the 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);
}}
and for the 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);
}}
I noticed there are some requests here for people wanting to know how to do this in XML. It is actually quite simple. This can be accomplished using a layer-list
Your button's drawable (drawable/some_button.xml):
<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>
And this is the highlighted drawable (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>
Now you can use this in any other xml:
...
android:drawable="@drawable/some_button"
...
I hope this helps someone in the future.
You can set color (tint) from xml.
Set transparent
(android:background="@null"
) for background
then use 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" />
I have the same issue and I found this solution :
logoImage.setOnTouchListener { v, event ->
if (event.action == MotionEvent.ACTION_DOWN) {
if (logoImage.isSelected) {
logoImage.setColorFilter(context.getColor(R.color.blue_unselect), PorterDuff.Mode.SRC_IN)
} else {
logoImage.setColorFilter(null)
}
} else if (event.action == MotionEvent.ACTION_UP) {
if (!logoImage.isSelected) {
logoImage.setColorFilter(null)
} else {
logoImage.setColorFilter(context.getColor(R.color.blue_unselect), PorterDuff.Mode.SRC_IN)
}
} else if (event.action == MotionEvent.ACTION_CANCEL) {
if (root.isSelected) {
logoImage.setColorFilter(null)
} else {
logoImage.setColorFilter(context.getColor(R.color.blue_unselect), PorterDuff.Mode.SRC_IN)
}
}
false
}
it's working for me.
As you defined the selector to be the src of the ImageButton Android will AFAIK just take the drawable because that's what matches the type of src. So tint won't be used.
Nevertheless, I had a similar problem: I also tried to use a selector like yours but for the android:tint value of the ImageButton instead of android:src. Of course I omitted the tint values you have in your selector. This would solve your problem, too, because you want to use the same drawable for all states. Curiously I get a NumberFormatException everytime stating that the system was unable to parse 'res/color/tint_selector.xml' (which is indeed my selector) as integer. To be specific my code looks like this:
This is my selector, saved in /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>
And this is the corresponding ImageButton:
<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>
Maybe this helps you a bit although it currently doesn't work.
精彩评论