Hello I am trying to place an imageview on an area where the user touches.
using MotionEvent event
Simply doing imageview.setX(event.getX()) and imageview.setY(event.getY()) is not the complete solution.
I realize these are pixel values, so I tried converting the event values to density independent values using (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, event.getX() , getResources()
.getDisplayMetrics());
but this still does not give me coordinates that match where I touch, when I try to show the imageview at this location.
Also, I am under the suspicion that the imageview draws its upper left corner at these coordinates, when I want the coordinates to be the at center of the imageview.
Insight appreciated
You will most likely want to do something like the following:
If you are trying to find the points on touch event points of a scaled image:
public static float[] getPointerCoords(ImageView view, MotionEvent e)
{
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix matrix = new Matrix();
view.getImageMatrix().invert(matrix);
matrix.postTranslate(view.getScrollX(), view.getScrollY());
matrix.mapPoints(coords);
return coords;
}
public boolean onTouch(View v, MotionEvent event)
{
float[] returnedXY = getPointerCoords((ImageView) v, event);
imageView.setLeft(returnedXY[0] + (imageView.getWidth() /2));
imageView.setTop(returnedXY[1] + (imageView.getHeight() /2));
}
if not, just use the events.getX and getY. You may need to use the getRawX and getRawY of the event.
Related
I am using CropView which extends an Android ImageView. It allows the image with in the the view to be scaled and moved around. there does not appear to be any public reference to the image position or scale. Is there a way to get the position of an image relative to a regular ImageView that I can try.
I have also tried setting a touch listener on the CropView that simply prints the x & y positions of the touch but i don see how i can use these to move get the updated position of the image.
mCropView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.d(TAG, "///" + event.getX() + " __ " + event.getY());
return false;
}
});
https://github.com/lyft/scissors/blob/master/scissors/src/main/java/com/lyft/android/scissors/CropView.java
The CropView itself is the viewport. Cropview has two methods getViewportWidth
and getViewportHeight. You'll need them.
The image that is scaled, moved, cropped etc is a Drawable. Drawable has a getBounds method that will return a Rect. You can get the top, left width and height from this Rect but you need to get the Drawable first.
CropView calls this Drawable "bitmap". You can get it calling the CropView's getImageBitmap() method.
Once you have it, call getBounds which gives you the image's Rect.
To get the x and y you want you'll have to do a bit of math with the Rect's top, left, width and height along with the viewport's height and width which you'll get from CropView's getViewportHeight and getViewportWidth methods.
Simply:
vpwidth=cropview.getViewPortWidth();
vpheight=cropview.getViewPortHeight();
imagetop=cropview.getImageBitmap().getBounds().top;
imageleft=cropview.getImageBitmap().getBounds().left;
imageheight=cropview.getImageBitmap().getBounds().height;
imagewidth=cropview.getImageBitmap().getBounds().width;
>math here
You could try out the method below,
final float[] getPointOfTouchedCordinate(ImageView view, MotionEvent e) {
final int index = e.getActionIndex();
final float[] coords = new float[] { e.getX(index), e.getY(index) };
Matrix m = new Matrix();
view.getImageMatrix().invert(m);
m.postTranslate(view.getScrollX(), view.getScrollY());
m.mapPoints(coords);
return coords;
}
you can get the value
mCropView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
float[] points = getPointOfTouchedCordinate(v, event);
Log.d(TAG, "///" + points[0] + " __ " + points(1));
return false;
}
});
I suggest to rely on pure xml and add to the Imagevie:
android:scaleType="centerCrop"
this will lead to the desired output as drawn.
i have little problem.
I'm getting an image,converting to Bitmap and fill imageview with this Bitmap.
So the problem is,how to take real coordinates(X,Y) of this Bitmap?
For better illustration, i attached an image:
As shown on picture, for e.g. i got an image with Custom Resolution,where user can make an perspective , via yellow points.
So i need to know,how to take real coords of bitmap from ImageView.
What i've made at current moment(but this approach isn't correct):
i take width/height from imageView and recreating new bitmap with this resolution.
Bitmap bt = Bitmap.CreateScaledBitmap(BitmapFactory.DecodeResource(Activity.Resources, Resource.Drawable.test),800,1420,false); //800 width 1420 height
imgView.SetImageBitmap(bt);
Via implementation of TouchListener(methods GetX()/GetY()),i get coords of points(yellow circle's that overlayed on Bitmap), and the problem is that these coordinates not correct.
Also its interesting for me case when i'm stretching bitmap via ScaleType.FitXY on imageView(its possible to take real coords of bitmap) ?
So how can i achieve my goal?
use ImageView#getImageMatrix, something like this:
final ImageView iv = new ImageView(this);
setContentView(iv);
// setup your image here by
// calling for example iv.setImageBitmap()
// or iv.setImageDrawable()
// or iv.setImageResource()
View.OnTouchListener otl = new View.OnTouchListener() {
Matrix inverse = new Matrix();
#Override
public boolean onTouch(View v, MotionEvent event) {
iv.getImageMatrix().invert(inverse);
float[] pts = {
event.getX(), event.getY()
};
inverse.mapPoints(pts);
Log.d(TAG, "onTouch x: " + Math.floor(pts[0]) + ", y: " + Math.floor(pts[1]));
return false;
}
};
iv.setOnTouchListener(otl);
I am overriding onInterceptTouch(MotionEvent) for the purpose of allowing horizontal scrolling. What I am finding however is that I cannot detect when the user has touched the embedded v. The x,y on the view are like 2000, 2400 while the MotionEvent.getX(),getY() are like 400,500
View v = findViewById(R.id.myView);
Rect r = new Rect();
v.getHitRect(r);
int[] loc = new int[2];
v.gtLocationOnScreen(loc);
int x = loc[0];
int y = loc[1];
// Result x,y are huge numbers 2400, etc
// event.getX() is 30, event.getY() == 500 nothing close to 2400.
if (r.contains((int)event.getX(), (int)event.getY())
{
return false; // this is never true even when I click right on View v.
}
I know this is an old question and is mostly answered in the linked post, but I just came across this problem so I thought I'd fill in my solution.
private boolean isTouchInView(View view, MotionEvent event) {
Rect hitBox = new Rect();
view.getGlobalVisibleRect(hitBox);
return hitBox.contains((int) event.getRawX(), (int) event.getRawY());
}
Try using getRawX() and getRawY(). These will give you the absolute positions you need.
See:
How do I know if a MotionEvent is relative or absolute?
You also have to adjust the location of your destination view to account for any displacement by other views like so:
int[] screenLocation = new int[2];
view.getLocationOnScreen(screenLocation);
hitRect.offset(screenLocation[0] - view.getLeft(), screenLocation[1] - view.getTop());
//Then check if source view is contained in target view
x=event.getRawX();
y=event.getRawY();
if (hitRect.contains(x, y)) {
//do your stuff
}
I want to scale view on touch event of ACTION_MOVE.
all bitmap are in square format. (point1= top+left, point2 =top+right, point3=bottom+left, point4=bottom+right)
i got the all four points.
when i drag the yellow gripper on top of the bitmap , red ball resize according to that (gripper can be move at any direction).
my question:
--> how should i calculate the distance of gripper center point and bitmap (left+top) point1 and scale according to bitmap.
means if i drag the bitmap from top+left corner then it scale/resize from point1,point2,point4 only (bottom+right corner remail at its position).
--> i am using canvas to draw bitmap, is it the rightway to handle bitmap scale/rotate ?
You can get the x,y coordinates on the event ACTION_DOWN and the x',y' coordinates on ACTION_UP. With the two points, you can make your measures (Euclidean Distance, for example).
gripper.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event) {
if(event.getAction() == android.view.MotionEvent.ACTION_DOWN){
x1 = event.getX();
y1 = event.getY();
}
else if(event.getAction() == android.view.MotionEvent.ACTION_UP){
x2 = event.getX();
y2 = event.getY();
}
return false;
}
});
You can also get the left,top position of the bitmap with getLeft(),getTop() methods (but note that these methods return the position relative to the View's parent layout).
There is an Matrix parameter on the createBitmap method that will allow you to resize your Bitmap and so you can store it with the resolution you want. See how here (it's an excellent tutorial, by the way). You probably already know how to do that, but I see no problem in sharing it anyway =P.
Hope it helps
I've drawn 5 bitmaps from .png files on a canvas - a head, a body and two arms and legs.
How can I detect which of these has been touched on an OnTouch? And, more specifically, can I detect if the OnTouch was within the actual shape of the body part touched?
What I mean is, obviously, the .pngs themselves are rectangular, but does Android know, or can I tell it, to ignore the transparency within the image?
You could get the colour of pixel touched and compare it to the colour of pixel on the background at those co-ords.
EDIT: ok, ignore that, you can't get the colour of a pixel on the canvas, so instead, get the x,y of the touch, check if any of the body part images have been touched, if so, take the x,y of the image from the touch x,y, then get the pixel of the image, which should be transparent or colour.
public boolean onTouchEvent(MotionEvent event)
{
int x = (int) event.getX();
int y = (int) event.getY();
int offsetx, offsety;
for(int i = 0;i<NUM_OF_BODY_PARTS;i++)
{
if(bodyPartRect[i].intersects(x,y,x+1,y+1))
{
offsetx = x - bodyPartRect[i].left;
offsety = y - bodyPartRect[i].top;
if(bodyPartBMP[i].getPixel(offsetx,offsety) == TRANSPARENT)
{
//whatever
}
}
}
}