I have an image (ImageView). I have certain areas on the image. When a use taps the screen, I want to detect which area was selected.
I have identified the area boundaries on the original image, but the x and y of MotionEvent are off.
I tried dip-to-pixel conversion (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dipValue, metrics)), but they are still off. It certainly has to do with the screen size / density / etc., but how exactly to get the pixel value of the touch event for the original image? (or, vice-versa - how to convert the original image coordinates to something that is comparable with the x and y of the motion event)
I managed to calculate it using the right and bottom coordinates of the ImageView (pic) compared to the real image size (568x1207).
float xCoef = 568f / pic.getRight();
float yCoef = 1207f / pic.getBottom();
float x = event.getX() * xCoef;
float y = event.getY() * yCoef;
Related
Assume I have a large screen device and a small screen device, now if I touched the large screen device at some random x,y like this:
//on touch event
float x = event.getX();
float y = event.getY();
And send these to the smaller screen device, how do I know on the small screen device where that x,y coordinate must be?
In other words if it was at the top right corner on the larger screen device, it must be at the top right corner on the small screen device
Most important for this is you need to have widths of both screens, and calculate it proportionally.
Suppose largeWidth = 400, smallWidth = 300, and your x on Large screen is 200.
Then if you have to calculate width on small screen, then simple math would help here.
smallX = x * smallWidth/LargeWidth
smallX = 200 * 300/400
smallX = 150
I have drawn a circle in a canvas with image in it on click event in one activity. And I have taken the x and y coordinates of that circle. In another activity i want to draw the same circle at the same position but the image size is not same so it is pointing to different position. So, how can achieve this?
The new position of circle (newX, newY) must move at same ratio that image size change.
newX = oldX * (newImageWidth / oldImageWidth)
newY = oldY * (newImageHeight / oldImageHeight)
You may want to change the size of the circle same way.
When drawing on view without zoom it works fine. See the screenshot
But when zooming and then drawing on view It is slightly up or down. See the screenshot
Here is my code for Custom View http://www.paste.org/78026 and for zoom http://www.paste.org/78027 and my xml http://www.paste.org/78028
Please can you tell me where I am wrong
Finally after lot of searching I found how to get relative X,Y when View is zoomed. It may be helpful to someone
// Get the values of the matrix
float[] values = new float[9];
matrix.getValues(values);
// values[2] and values[5] are the x,y coordinates of the top left corner of the drawable image, regardless of the zoom factor.
// values[0] and values[4] are the zoom factors for the image's width and height respectively. If you zoom at the same factor, these should both be the same value.
// event is the touch event for MotionEvent.ACTION_UP
float relativeX = (event.getX() - values[2]) / values[0];
float relativeY = (event.getY() - values[5]) / values[4];
I'm trying to make a custom view with clickeable areas for my app. Those areas are relative to the image pixel coords that will fill that view. I've placed those images at drawable-nodpi to avoid system scaling.
My custom view takes one of those images, resizes it keeping the aspect ratio to fit its parent and then resizes the view to the size of the resulting image. So at this point I have a view that maintains the ratio of the source, so the resulting view click (onTouch event.getX and event.getY) coordinates are relative to the original image pixel coords.
From the other hand I have all the coordinates of the shapes that define the clickeable areas in a xml file wich I load when my activity starts. Those areas are defined by a type: circle or rect.
circle: center x-y and radius in px according to the original image
rect: center x-y, width and height in px according to the original image
Now I need to detect if my touch x-y is inside of the coordinates of any of those areas, but keeping in mind the scaling that my original image suffered.
How could I detect the "collitions" between my touch coordinates and the clickeable areas coords? I mean how do I calculate that even without resizing my original image?
I have made a View like this myself,
i added objects containing an image and x/y coords.
Now u need to have a list of those Objects, and in case you get an ontouchEvent, you iterate over that list do something like objectHit()
public boolean objectHit(int x, int y){
int touchdistance = Math.sqrt((double)(this.getX()-x)*(double)(this.getX()-x)) + ((double)(this.getY()-y)*(double)(this.getY()-y));
return touchdistance <= this.getTouchableArea();
}
And you implement getTouchableArea for the Object basicly the same way.
public double getTouchAbleArea() {
return Math.sqrt(Math.pow(getBitmap().getHeight(),2)+Math.pow(getBitmap().getWidth(),2))/2;
}
So what you are doing with this code is, you determine if the touch is within the size of the Image representing the object.
This is what I ended up doing
for(i=0;i<level.getDiffs();i++){
DifferencesData diff = level.getDifference(i);
if(!diff.getFinded()){
x = diff.getX();
y = diff.getY();
if(diff.getType() == 0){
double d = Math.sqrt(Math.pow(x - event.getX(),2) + Math.pow(y - event.getY(),2));
if(d <= diff.getRadius()){
hit = true;
break;
}
}else{
double dx = Math.sqrt(Math.pow(x - event.getX(),2));
double dy = Math.sqrt(Math.pow(y - event.getY(),2));
if(dx <= (diff.getWidth() / 2) && dy <= (diff.getHeight() / 2)){
hit = true;
break;
}
}
}
}
First I scaled the original coordinates by the same scale that my image was scaled by. Then, inside an OnTouchListener I calculated the distance of my touch to the ratio of the circle, or to the half width and half height of my rectangles.
Thank you Daniel for your help!
I have set a prescaled Bitmap as ImageView's source. Then I've read Matrix of an ImageView and shift Bitmap of an ImageView via matrix.postTranslate(shiftX, shiftY).
Now I want to zoom in / out and image while maintaining center of ImageView at the same point of Bitmap that was before scale.
If I try to zoom in an image with matrix.postScale(zoom, zoom), point that I want to maintain (blue dot) shifts to other place (purple dot).
I have tried several different ways to shift Bitmap back, but I cant get it to work correctly. I know initial Bitmap size, ImageView size, distances marked by doted line. Tried to calculate needed shift and use matrix.postTranslate(-zoomshiftX, -zoomshiftY) afterwards, but it doesn't shift correctly.
Even found out, that underlying Bitmap's pixel count doesnt change after matrix.postScale() function and tried matrix.postTranslate(-zoomshiftX/zoom, -zoomshiftY/zoom) - but still no luck.
How do I achieve such zoom?
Take a look at my question here regarding creating a zoomable ViewGroup. I've described code snippets from my end solution, and some of it might be helpful.
Extending RelativeLayout, and overriding dispatchDraw() to create a zoomable ViewGroup
Maybe this can be helpful:
If you got two fingers on screen, you can get the event of the two fingers and get the mid point:
PointF mid;
MotionEvent event;
float x = event.getX(0) - event.getX(1);
float y = event.getY(0) - event.getY(1);
mid.set(x / 2, y / 2);
Then you can set the scalation having the mid point in the center of the screen:
matrix.postScale(scale, scale, mid.x, mid.y);