In Android, when I set a background image to a button, I can not see any effect on it when it's clicked.
I need to set some effect on the button, so the user can recognise that the button is clicked.
The button should be dark for a few seconds when it is clicked. How to do this?
This can be achieved by creating a drawable xml file containing a list of states for the button. So for example if you create a new xml file called "button.xml" with the following code:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:state_pressed="false" android:drawable="#drawable/YOURIMAGE" />
<item android:state_focused="true" android:state_pressed="true" android:drawable="#drawable/gradient" />
<item android:state_focused="false" android:state_pressed="true" android:drawable="#drawable/gradient" />
<item android:drawable="#drawable/YOURIMAGE" />
</selector>
To keep the background image with a darkened appearance on press, create a second xml file and call it gradient.xml with the following code:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
<bitmap android:src="#drawable/YOURIMAGE"/>
</item>
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<gradient android:angle="90" android:startColor="#880f0f10" android:centerColor="#880d0d0f" android:endColor="#885d5d5e"/>
</shape>
</item>
</layer-list>
In the xml of your button set the background to be the button xml e.g.
android:background="#drawable/button"
Changed the above code to show an image (YOURIMAGE) in the button as opposed to a block colour.
It is simpler when you have a lot of image buttons, and you don't want to write xml-s for every button.
Kotlin Version:
fun buttonEffect(button: View) {
button.setOnTouchListener { v, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> {
v.background.setColorFilter(-0x1f0b8adf, PorterDuff.Mode.SRC_ATOP)
v.invalidate()
}
MotionEvent.ACTION_UP -> {
v.background.clearColorFilter()
v.invalidate()
}
}
false
}
}
Java Version:
public static void buttonEffect(View button){
button.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(0xe0f47521,PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.getBackground().clearColorFilter();
v.invalidate();
break;
}
}
return false;
}
});
}
Create your AlphaAnimation Object that decides how much will be the fading effect of the button, then let it start in the onClickListener of your buttons
For example :
private AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
// some code
public void onClick(View v) {
v.startAnimation(buttonClick);
}
of course this is just a way, not the most preferred one, it's just easier
You can simply use foreground for your View to achieve clickable effect:
android:foreground="?android:attr/selectableItemBackground"
For use with dark theme add also theme to your layout (to clickable effect be clear):
android:theme="#android:style/ThemeOverlay.Material.Dark"
To make your item consistent with the system look and feel try referencing the system attribute android:attr/selectableItemBackground in your desired view's background or foreground tag:
<ImageView
...
android:background="?android:attr/selectableItemBackground"
android:foreground="?android:attr/selectableItemBackground"
...
/>
Use both attributes to get desired effect before/after API level 23 respectively.
https://stackoverflow.com/a/11513474/4683601
Or using only one background image you can achive the click effect by using setOnTouchListener
Two ways
((Button)findViewById(R.id.testBth)).setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
Button view = (Button) v;
view.getBackground().setColorFilter(0x77000000, PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP:
// Your action here on button click
case MotionEvent.ACTION_CANCEL: {
Button view = (Button) v;
view.getBackground().clearColorFilter();
view.invalidate();
break;
}
}
return true;
}
});
And if you don't want to use setOnTouchLister, the another way of achieving this is
myButton.getBackground().setColorFilter(.setColorFilter(0xF00, Mode.MULTIPLY);
StateListDrawable listDrawable = new StateListDrawable();
listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
listDrawable.addState(new int[] {android.R.attr.defaultValue}, myButton);
myButton.setBackgroundDrawable(listDrawable);
For all the views
android:background="?android:attr/selectableItemBackground"
But for cardview which has elevation use
android:foreground="?android:attr/selectableItemBackground"
For Circular click effect as in toolbar
android:background="?android:attr/actionBarItemBackground"
Also you need to set
android:clickable="true"
android:focusable="true"
This is the best solution I came up with taking hints from #Vinayak's answer. All the other solutions have different drawbacks.
First of all create a function like this.
void addClickEffect(View view)
{
Drawable drawableNormal = view.getBackground();
Drawable drawablePressed = view.getBackground().getConstantState().newDrawable();
drawablePressed.mutate();
drawablePressed.setColorFilter(Color.argb(50, 0, 0, 0), PorterDuff.Mode.SRC_ATOP);
StateListDrawable listDrawable = new StateListDrawable();
listDrawable.addState(new int[] {android.R.attr.state_pressed}, drawablePressed);
listDrawable.addState(new int[] {}, drawableNormal);
view.setBackground(listDrawable);
}
Explanation:
getConstantState().newDrawable() is used to clone the existing Drawable otherwise the same drawable will be used. Read more from here:
Android: Cloning a drawable in order to make a StateListDrawable with filters
mutate() is used to make the Drawable clone not share its state with other instances of Drawable. Read more about it here:
https://developer.android.com/reference/android/graphics/drawable/Drawable.html#mutate()
Usage:
You can pass any type of View (Button, ImageButton, View etc) as the parameter to the function and they will get the click effect applied to them.
addClickEffect(myButton);
addClickEffect(myImageButton);
just wanna add another easy way to do this: If your ImageButton remains its background and you don't set it to null, it will work like a normal button and will show the click animation while clicking exactly like other buttons.The way to hide the background while it is still there:
<ImageButton
android:id="#+id/imageButton2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingBottom="1dp"
android:paddingLeft="1dp"
android:paddingRight="1dp"
android:paddingTop="1dp"
android:src="#drawable/squareicon" />
The paddings won't let the background be visible and make the button act like other buttons.
Step: set a button in XML with onClick Action:
<Button
android:id="#+id/btnEditUserInfo"
style="?android:borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="#dimen/txt_height"
android:layout_gravity="center"
android:background="#drawable/round_btn"
android:contentDescription="#string/image_view"
android:onClick="edit_user_info"
android:text="Edit"
android:textColor="#000"
android:textSize="#dimen/login_textSize" />
Step: on button clicked show animation point
//pgrm mark ---- ---- ----- ---- ---- ----- ---- ---- ----- ---- ---- -----
public void edit_user_info(View view) {
// show click effect on button pressed
final AlphaAnimation buttonClick = new AlphaAnimation(1F, 0.8F);
view.startAnimation(buttonClick);
Intent intent = new Intent(getApplicationContext(), EditUserInfo.class);
startActivity(intent);
}// end edit_user_info
I had the same issue, where I needed to have a transparent background but still get animation. Setting this solved it for me:
android:background="?android:selectableItemBackground"
Also this if you want to have circular effect:
android:background="?android:selectableItemBackgroundBorderless"
Use RippleDrawable for Material Design state pressed/clicked effect. In order to achieve this, create ripple item as an .xml under /drawable folder and use it in android:background for any views.
Effect for icon pressed/clicked, use circular ripple effect, for example:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#android:color/darker_gray"
/>
Effect for view clicked with rectangle boundary, we can add ripple over the existing drawable like bellow:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#000000">
<item android:drawable="#drawable/your_background_drawable"/>
</ripple>
Create bounce.xml file fo animation
LOCATION:
res->anim->bounce.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale
android:duration="100"
android:fromXScale="0.9"
android:fromYScale="0.9"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>
Add this line in onClick to initialize
final Animation myAnim = AnimationUtils.loadAnimation(this,R.anim.bounce);
button.startAnimation(myAnim);
You get the shrink effect in a button click.
Simple and easy way to set View click effect.
Method
public AlphaAnimation clickAnimation() {
return new AlphaAnimation(1F, 0.4F); // Change "0.4F" as per your recruitment.
}
Set in View
yourView.startAnimation(clickAnimation());
Making a minor addition to AndrĂ s answer:
You can use postDelayed to make the color filter last for a small period of time to make it more noticeable:
#Override
public boolean onTouch(final View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
v.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
v.invalidate();
break;
}
case MotionEvent.ACTION_UP: {
v.postDelayed(new Runnable() {
#Override
public void run() {
v.getBackground().clearColorFilter();
v.invalidate();
}
}, 100L);
break;
}
}
return false;
}
You can change the value of the delay 100L to suit your needs.
If you're using xml background instead of IMG, just remove this :
<item>
<bitmap android:src="#drawable/YOURIMAGE"/>
</item>
from the 1st answer that #Ljdawson gave us.
Related
my xml file
<LinearLayout
android:id="#+id/fragmentSelectorArea"
android:layout_width="fill_parent"
android:layout_height="#dimen/main_seletor_height"
android:layout_marginBottom="#dimen/main_seletor_margin_bottom"
android:background="#color/mainBtnBg" >
<ImageButton
android:id="#+id/myBtn"
android:layout_width="0dp"
android:layout_height="#dimen/main_btn_height"
android:layout_weight="1"
android:background="#drawable/btn_selector" />
</LinearyLayout>
btn_selector.xml
<item android:state_pressed="true"
android:drawable="#drawable/pressed_btn" />
<item android:state_focused="true"
android:drawable="#drawable/focused_btn" />
<item android:drawable="#drawable/nonselected_btn"/>
activity.java
ImageButton btn1 = (ImageButton) findViewById(R.id.myBtn);
OnClickListener btnListener = new OnClickListener() {
#Override
public void onClick(View btn) {
switch (btn.getId()) {
case R.id.myBtn:
mPager.setCurrentItem(0);
break;
...
default:
break;
}
}
};
btn1.setOnClickListener(btnListener);
I want to use effect when I clicked buttons.
normal(no focused), focused, pressed<-
But the state_focused is not working.
So I can't see focused effect.
Please help me..
add image.
I solved it.
button selector just two case. (pressed, non-pressed)
I overriding onPageChangeListener() in ViewPagerIndicator.
state_focused applied whenever the button is focused on using a dpad or the trackball. Views don't generally show a focused state when using touch.
You can use setonTouchListener to create an effect on the touch of your ImageButton like ...
myBtn.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN)
myBtn.setImageResource(R.drawable.quit_yes_selected);
else if(event.getAction() == MotionEvent.ACTION_UP)
myBtn.setImageResource(R.drawable.quit_yes);
return false;
}
});
Or you ca simply create an btn_selector.xml file in your drawable and set that to your ImageBackgroundResource like
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- When selected, you should use bg with grey -->
<item android:drawable="#drawable/pressed_btn"
android:state_selected="true" />
<!-- When not selected, you should use bg with white -->
<item android:drawable="#drawable/nonselected_btn" />
</selector>
And in the java you have to assign your ImageButton background resource as that file
myBtn.setBackgroundResource(R.drawable.btn_selector);
I dynamically generate TextViews which work like buttons. Now i want to highlight them when they get pressed. Something like change Text color or background color.
I have tried to use selector, but it doesn't work.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="#ffffff"/>
<item android:state_pressed="true" android:state_enabled="false" android:color="#ffffff" />
</selector>
Here my loop for creating the TextViews.
int z = 0;
for (MOKGenericDataItem d : data) {
if (d.getButtonText() != null) {
final int pagePosition = z;
TextView btn = new TextView(getActivity());
btn.setId(z);
final int id_ = btn.getId();
btn.setText(d.getButtonText());
btn.setTextSize(TypedValue.COMPLEX_UNIT_SP, 30);
btn.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1f));
btn.setGravity(Gravity.CENTER);
mLineareLayoutViewPagerButtons.addView(btn);
btn1 = ((TextView) view.findViewById(id_));
btn1.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
mViewPager.setCurrentItem(pagePosition,false);
}
});
}
z++;
}
First of all your this line is creating ambiguity as you are taking a variable name as btn1 (which is relating it to button)and you are taking a reference of TextView,
btn1 = ((TextView) view.findViewById(id_));
Anyways,Go step by step,
create an xml like label_bg.xml like the following in the drawable folder:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/pressed_color"
android:state_pressed="true" />
<item android:drawable="#drawable/normal_color" />
</selector>
In values folder create another xml like the following,named as labelcolors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<drawable name="pressed_color">#7ec0ee</drawable> <!--custom color for pressed state -->
<drawable name="normal_color">#00FFFFFF</drawable> <!--transperent color for normal state -->
</resources>
Now set the background of the label as label_bg.xml
<TextView
android:id="#+id/yourlabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="760dp"
android:layout_marginTop="515dp"
android:background="#drawable/label_bg" <!--like this-->
android:text="LabelText"
android:textSize="20dp" />
as you are dynamically adding the views so you need to set the background for your each textView programatically .For that call setBackgroundResource() on the textview object created and set label.xml as background
You need to create a class implements with OnTouchListener and Detect touch Motin. ACTION_DOWN, change text color and ACTION_UP change it's default color according to your requirement.
Code:
public class CustomTouchListener implements View.OnTouchListener {
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
((TextView) view).setTextColor(0xFFFFFFFF); // white
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
((TextView) view).setTextColor(Color.parseColor("#4a4a4a")); // lightblack
break;
}
return false;
}
}
Now set TouchListener using
textView.setOnTouchListener(new CustomTouchListener());
So I am making an app with 3 buttons. Currently I have the following .xml file that makes them have rounded off edges and be the colour red. Now I want to to make them so if one is selected then that button turns green while the other two remain, or turn back to red. How could I go about doing this? Do I have to make another .xml file?
Here is my drawable .xml file for the buttons:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" android:padding="10dp">
<!--red colour.-->
<solid android:color="#FF0000"/>
<corners
android:bottomRightRadius="10dp"
android:bottomLeftRadius="10dp"
android:topLeftRadius="10dp"
android:topRightRadius="10dp"/>
<stroke android:width="2px" android:color="#000000"/>
</shape>
Use a selector as follows:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- green state -->
<item
android:drawable="#drawable/button_selected"
android:state_selected="true"></item>
<!-- green state -->
<item
android:drawable="#drawable/button_pressed"
android:state_pressed="true"></item>
<!-- red state -->
<item
android:drawable="#drawable/button_disabled"></item>
</selector>
Then, you should call this selector like:
<Button
...
android:background="#drawable/my_selector" />
And create each drawable.xml (as your example for the red button) for every state: button_selected, button_pressed and button_disabled.
You can also remain the state by using onTouchListener like:
button.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// change the color
return true;
case MotionEvent.ACTION_UP:
// intitial color
return true;
default:
return false;
}
}
});
However, it's better to use a Selector and a background, this use less resource.
UPDATE:
You can use a setBackgroundResource method to remain and change the background state of clicked button as follows:
// 1st clicklistener method
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.green_drawable);
button2.setBackgroundResource(R.drawable.selector_drawable);
}
}
// 2nd clicklistener method
button2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundResource(R.drawable.green_drawable);
button1.setBackgroundResource(R.drawable.selector_drawable);
}
}
Not tested but it should work.
How I can change the background color to a View this under a button when I click the button? I've tried a selector does not work because the View not change the color. What is the problem?
This is my code:
XML
...
<View
android:id="#+id/viewPlanos2"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_gravity="center" />
<Button
android:id="#+id/button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1"
android:background="#color/transparente"
android:drawableTop="#drawable/buttonimage"
android:gravity="center"
android:paddingTop="50dp" />
<View
android:id="#+id/viewPlanos1"
android:layout_width="match_parent"
android:layout_height="3dp"
android:layout_gravity="center" />
...
JAVA
View linea2 = (View)findViewById(R.id.viewPlanos2);
linea2.setBackgroundColor(getResources().getColor(R.drawable.linea_verde));
linea_verde
<item android:state_pressed="true"><shape>
<gradient android:angle="90" android:endColor="#color/azul" android:startColor="#color/azulOscuro" />
</shape></item>
<item android:state_focused="true"><shape>
<gradient android:angle="90" android:endColor="#color/azul" android:startColor="#color/azulOscuro" />
</shape></item>
<item><shape>
<solid android:color="#color/rojo" />
</shape></item>
EDIT:
I have tried:
public void onClick(View v) {
if(v == botonMetro) {
linea2.setBackgroundResource(R.drawable.linea_verde);
and
linea2.setBackgroundColor(getResources().getColor(R.drawable.linea_verde));
}
}
But the code not work
You are wrongly using drawable use this one one
view.setBackgroundResource(R.drawable.linea_verde)
as you say change the background color to a View this under a button when I click the button
do like this
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// change color of your view here
linea2.setBackgroundColor(getResources().getColor(R.drawable.linea_verde));
}
});
setBackgroundColor() is for colors only, but it seems your using a state list drawable. If you are sure you want to use a different color depending on the Button's state, set the state list drawable using this code:
view.setBackgroundDrawable(R.drawable.linea_verde);
Otherwise, just set the background color using
view.setBackgroundColor(getResources().getColor(R.drawable.yourcolor);
But in this case, use a click listener, and also make sure to actually use a color resource, e.g.:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="opaque_red">#f00</color>
<color name="translucent_red">#80ff0000</color>
</resources>
You can also do like this.
android:background="#drawable/linea_verde"
If you would like to apply default background of selected item you could use background attribute with android ?attr.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/selectableItemBackground" />
selectableItemBackground attribute will use proper drawable according to Android version. On pre-lollipop it will use solid background, but on lollipop devices the ripple effect will be used.
Code from: com.android.support/appcompat-v7/23.0.0/res/values/values.xml
<item name="selectableItemBackground">#drawable/abc_item_background_holo_dark</item>
public void onClick(View v) {
int id = v.getId();
if(id == R.id.button) {
linea2.setBackgroundResource(R.drawable.linea_verde);
}
}
I think you were comparing the view the wrong way. I just happened to stumble to this question and since it is not marked as answered, this might help others.
Create two separate files for your shapes and change the background of your view after button click:
private boolean isPressed = false;
public void onClick(View v) {
if(v == botonMetro) {
if(isPressed){
linea2.setBackgroundResource(R.drawable.pressed_shape);
} else{
linea2.setBackgroundResource(R.drawable.un_pressed_shape);
}
isPressed = !isPressed;
}
}
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" 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.