Skip to content

Instantly share code, notes, and snippets.

@trynx
Last active January 9, 2020 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trynx/501faf7f79a6547e01d8933caaa0f539 to your computer and use it in GitHub Desktop.
Save trynx/501faf7f79a6547e01d8933caaa0f539 to your computer and use it in GitHub Desktop.
Android - Get touch on specific view by pixel
public class ActionTouch implements View.OnTouchListener {
private View.OnClickListener onClickListener;
public ActionTouch(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_UP){
// The on touch is implemented on a the viewgroup which holds the views we want to get the touch of
ViewGroup viewGroup = (ViewGroup)v;
// Should go from the last child to the first child, the deeper the child is in the UI, the lower index it is
for (int pos = viewGroup.getChildCount() - 1; pos >= 0 ; pos--) {
// Child view, which is a relative layout, which holds the view with the image
View rlView = viewGroup.getChildAt(pos);
View view = rlView.findViewById(R.id.iv_modify);
// Will save in rect the position bounds of the rlView
Rect r = new Rect(0, 0, rlView.getWidth(), rlView.getHeight());
viewGroup.getChildVisibleRect(rlView, r, new Point(0, 0));
// Only if the touch was in the bounds of the rlView, it's considerate as touched
boolean isTouched = event.getRawX() >= r.left && event.getRawX() <= r.right && event.getRawY() >= r.top && event.getRawY() <= r.bottom;
if(!isTouched) continue;
// For image views, check whether it touched on a colored pixel or transparent background
Bitmap bitmap = getBitmapFromDrawable(((ImageView) view).getDrawable(), view.getWidth(), view.getHeight());
// Calculate the offset of x & y depend on raw touch and rlView rect
int x = (int) (event.getRawX() - r.left);
int y = (int) (event.getRawY() - r.top);
// Didn't touch on a colored pixel of image
if (bitmap.getPixel(x, y) == Color.TRANSPARENT)
continue;
if (onClickListener != null) {
onClickListener.onClick(view);
break;
}
}
}
return true;
}
/**
* https://stackoverflow.com/questions/33696488/getting-bitmap-from-vector-drawable
*
* @param drawable
* @return
*/
public Bitmap getBitmapFromDrawable(Drawable drawable, int newWidth, int newHeight) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(newWidth,
newHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
}
GestureDetectorCompat gestureDetectorCompat = new GestureDetectorCompat(this, new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent motionEvent) {
// Get the drawable of the view, and make a copy of it, so the original drawable doesn't get modified
Drawable imgDrawable = ((ImageView)touchedView).getBackground().getConstantState().newDrawable().mutate();
// For vectories drawable, create a bitmap with this method
Bitmap bitmap = getBitmapFromVectorDrawable(imgDrawable, touchedView.getWidth(), touchedView.getHeight());
// For other type of drawable
// Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), imgDrawable /* OR R.drawable.icon*/);
int pixel = bitmap.getPixel((int) motionEvent.getX(), (int) motionEvent.getY());
String colorHex = Integer.toHexString(pixel);
System.out.println("Touched color in view " + colorHex);
// When touching on a zone without any color or alpha, it will return 0 in the pixel
// So to continue to the next view in the same position, shouldn't consume the click on this view
return !colorHex.equals("0");
}
public static Bitmap getBitmapFromVectorDrawable(Drawable drawable, int newWidth, int newHeight) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
drawable = (DrawableCompat.wrap(drawable)).mutate();
}
Bitmap bitmap = Bitmap.createBitmap(newWidth,
newHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment