The app I\'m currently working on uses a lot of ImageViews as buttons. The graphics on these buttons use the alpha channel to fade out the edges of the button and make them look
For those who have encountered a similar need, solving this in code is fairly clean. Here is a sample:
public class TintableButton extends ImageView {
private boolean mIsSelected;
public TintableButton(Context context) {
super(context);
init();
}
public TintableButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TintableButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
mIsSelected = false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN && !mIsSelected) {
setColorFilter(0x99000000);
mIsSelected = true;
} else if (event.getAction() == MotionEvent.ACTION_UP && mIsSelected) {
setColorFilter(Color.TRANSPARENT);
mIsSelected = false;
}
return super.onTouchEvent(event);
}
}
It's not finished but works well as a proof of concept.
I think this solution is simple!
Step 1: Create res/drawable/dim_image_view.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:drawable="@drawable/dim_image_view_normal"/> <!-- focused -->
<item android:state_pressed="true" android:drawable="@drawable/dim_image_view_pressed"/> <!-- pressed -->
<item android:drawable="@drawable/dim_image_view_normal"/> <!--default -->
</selector>
Step 2: Create res/drawable/dim_image_view_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item><bitmap android:src="@mipmap/your_icon"/></item>
</layer-list>
Step 3: Create res/drawable/dim_image_view_pressed.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item><bitmap android:src="@mipmap/your_icon" android:alpha="0.5"></bitmap></item>
</layer-list>
Step 4: Try setting the image in xml layout as:
android:src="@drawable/dim_image_view"
Your answer was excellent :)
However instead of creating a button object, I am only calling an OnTouchlistener to change the state of every view.
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Drawable background = v.getBackground();
background.setColorFilter(0xBB000000, PorterDuff.Mode.SCREEN);
v.setBackgroundDrawable(background);
} else if (event.getAction() == MotionEvent.ACTION_UP) {
Drawable background = v.getBackground();
background.setColorFilter(null);
v.setBackgroundDrawable(background);
}
return true;
}
Gives the same results though
You can use a class I've created https://github.com/THRESHE/TintableImageButton Not exactly the best solution but it works.
You can combine StateListDrawable
and LayerDrawable
for this.
public Drawable getDimmedDrawable(Drawable drawable) {
Resources resources = getContext().getResources();
StateListDrawable stateListDrawable = new StateListDrawable();
LayerDrawable layerDrawable = new LayerDrawable(new Drawable[]{
drawable,
new ColorDrawable(resources.getColor(R.color.translucent_black))
});
stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, layerDrawable);
stateListDrawable.addState(new int[]{android.R.attr.state_focused}, layerDrawable);
stateListDrawable.addState(new int[]{android.R.attr.state_selected}, layerDrawable);
stateListDrawable.addState(new int[]{}, drawable);
return stateListDrawable;
}
I assume our colors.xml looks like this
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="translucent_black">#80000000</color>
</resources>
I think this solution is simple enough:
final Drawable drawable = ... ;
final int darkenValue = 0x3C000000;
mButton.setOnTouchListener(new OnTouchListener() {
Rect rect;
boolean hasColorFilter = false;
@Override
public boolean onTouch(final View v, final MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
rect = new Rect(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
drawable.setColorFilter(darkenValue, Mode.DARKEN);
hasColorFilter = true;
break;
case MotionEvent.ACTION_MOVE:
if (rect.contains(v.getLeft() + (int) motionEvent.getX(), v.getTop()
+ (int) motionEvent.getY())) {
if (!hasColorFilter)
drawable.setColorFilter(darkenValue, Mode.DARKEN);
hasColorFilter = true;
} else {
drawable.setColorFilter(null);
hasColorFilter = false;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
drawable.setColorFilter(null);
hasColorFilter = false;
break;
}
return false;
}
});