Last active
January 9, 2020 13:35
-
-
Save trynx/501faf7f79a6547e01d8933caaa0f539 to your computer and use it in GitHub Desktop.
Android - Get touch on specific view by pixel
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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