Get the real X/Y position of an onTouch Event - android

I know there are some similar topics that have been posted, but I couldn’t find a good solution for my problem.
I have a GridView which is filed with a custom ImageAdapter. Everything works fine, but whenever I click on an image contained in the GridView, I would like to move another Imageview at the click's position.
However, the coordinates of the Event, that I take with event.getX() and event.getY(), don’t correspond to the click’s position.
I first thought of a problem of dp/px conversion, and I tried several solutions in this way but none of them worked.
Then I tried to use the getXPrecision(), but I couldn’t make a working solution…
Maybe there is another way?
I would like to make the correct position programmatically, without adding constants int, so my project will work on various phone and tablet, with different dp and resolutions.
EDIT : Here is a screenshot, where i clicked the 3rd cell of the first line, and setted the position of the pencil with getRawX() - getRawY(). As we can see, this is not the correct position, I want the red dot (imageview's center) to be positionned where i clicked.
The code used :
//getting the position of the onTouch event :
GridView centre = (GridView) findViewById(R.id.gridView);
adapter = new ImageAdapter(this, (dim * dim), tailleCell);
centre.setAdapter(adapter);
centre.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
int X = (int)event.getRawX();
int Y = (int)event.getRawY();
animation(X, Y, etat);
return false;
}
});`
//launching the animation (and setting position of the pencil) :
private void animation(int posX, int posY, int etat)
{
final ImageView img;
if(etat == 0)
{
img = (ImageView) findViewById(R.id.imageView);
}
else
{
img = (ImageView) findViewById(R.id.imageView2);
}
img.clearAnimation();
img.setVisibility(View.VISIBLE);
img.setX(posX);
img.setY(posY);
[...]
}
EDIT 2 : ~Solution :
Jesus Molina Rodríguez De Vera's solution wasn't working as expected, but i managed to make a workable solution. I just changed my code in the Event Handler to adjust the image's position :
int[] offset = new int[2];
centre.getLocationOnScreen(offset);
int Xoffset=offset[0];
int Yoffset = offset[1];
int X = (int)event.getRawX();
int Y = (int)event.getRawY();
animation(X-((int)Math.round(Xoffset/1.15)), Y-((int)Math.round(Yoffset/1.5)), etat);
Sorry for my bad English :)
Thanks for your help!

Try using getRawX() and getRawY() instead of getX and getY.
Edit
I think that i have found the problem.
You are obtaining X and Y relative to the GridView top-left corner, not to the absolute screen coordinetes.
What you can do is the following:
int[] offset = new int[2];
center.getLocationOnScreen(offset);
int Xoffset=offset[0];
int Yoffset = offset[1];
private void animation(int posX, int posY, int etat){
//...
img.setX(posX+Xoffset);
img.setY(posY+Yoffset);
[...]
}
This is supposed to set the the top-left corner of the ImageView in the selected point. In order to set the center in that point:
int ivWidth = img.getWidth();
int ivHeight = img.getHeight();
private void animation(int posX, int posY, int etat){
//...
int[] finalPosition=new int[2];
finalPosition[0] = posX+Xoffset-(ivWidth/2);
finalPosition[1] = posY+Yoffset-(ivHeight/2);
img.setX(finalPosition[0]);
img.setY(finalPosition[1]);
[...]
}
I haven't try it but it should work.
Edit 2
Xoffset and Yoffset are only needed if you use getX()/getY() instead of getRawX()/getRawY()

Related

Is There any way to Predict x and y location from one screen size to another?

i am developing an android app, about joining dots and making picture.
so far i can't find a way to extract exact x and y coordinates of black dots . so I've hard coded x and y locations to draw point on exact black dot of image. It worked wonderful on 1152*720 size ,but problem occurs when i tested it on 480*600 size , dots misplaced from there exact location , now
My Question is if I've written something like :
x = 100 ,
y = 200
(on screen 1152*720)
what will be x and y values in different screen sizes like 480*600 and how to calculate it ? i know it is silly question but i am new to this stuff.
Answering your question as you have asked it...
int oldScreenX // The current x coord
int newScreenX // The new x coord
...
float oldScreenSizeX = 1152.0f;
float newScreenSizeX = 600.0f;
newScreenX = (int)(oldScreenX / oldScreenSizeX) * newScreenSizeX; // Remember to cast the result back to an int
Do the same for y.
Additional:
Perhaps you should reconsider your approach.
The real problem is how do you put the dot in the same location on the Image, if the Image is being drawn at a different size. So forget about measuring the screen size. Measure the Image size instead.
For example, if you are showing your image in an ImageView, you could write a general scaling method like the following:
public int scaleCoordinate(int unscaledImageSize, int scaledImageSize, int unscaledCoordinate) {
scaledCoordinate = (int)(unscaledCoordinate / unscaledImageSize) * scaledImageSize; // Remember to cast the result back to an int
return scaledCoordinate;
}
Then you can use it in your code, something like:
ImageView imageView = (ImageView)findViewById(R.id.my_imageview);
Drawable drawable = image.getDrawable();
// Get the original size of the bitmap
int unscaledSizeX = drawable.getIntrinsicWidth();
// Get the current size it is being drawn at on the screen
int scaledSizeX = imageView.getWidth();
int scaledCoordinateX = scaleCoordinate(unscaledSizeX, scaledSizeX, unscaledCoordinateX);
NOTE:
The ImageView needs to be measured and laid out by the system before calling the above code. If you call it too early imageView.getWidth() will return 0.
It would be best to call the above code once the ImageView is actually displayed on the screen (from your onResume() or later).
I was done this, while studying java may be it will be helpful for you.
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
public class DrawLineOnGivenLocations extends Applet implements MouseListener, MouseMotionListener{
int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
public void init() {
addMouseListener(this);
addMouseMotionListener(this);
}
public void mouseMoved(MouseEvent me) {
// show status
showStatus("Moving mouse at " + me.getX() + ", " + me.getY());
}
public void mouseClicked(MouseEvent me) {
// save coordinates
x1 = me.getX();
y1 = me.getY();
x2 = me.getX();
y2 = me.getY();
repaint();
}
public void paint(Graphics g){
g.drawLine(x1,y1 ,x2, y2);
}
public void mouseEntered(MouseEvent arg0) {}
public void mouseDragged(MouseEvent arg0) {}
public void mouseExited(MouseEvent arg0) {}
public void mousePressed(MouseEvent arg0) {
//repaint();
}
public void mouseReleased(MouseEvent arg0) {}
}

view.getHitRect(rect) not working

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
}

How to get Center of an Imageview which is a circle

Now I have an ImgeView which a circle and I want to find the center point of that circle so I have tried the following code but it seems not working
int[] location = new int[2];
imageView.getLocationOnScreen(location);
int radius=imageView.getHeight()/2;
int[] center=new int[2];
center[0]=location[0]+radius;
center[1]=location[1]+radius;
so the coordinates I got by "location" is top point of the imageview or not ?
Please help me how to get a center point of an imageview.
I assumed below situation:
You will be loading an ImageView(either from xml or code) and have a reference to the same in myImageView(say). Now, you wish to calculate the centre of the myImageView irrespective of its position on the screen.
If my assumption is correct then probably below is the solution you are looking for:
int centerXOnImage=myImageView.getWidth()/2;
int centerYOnImage=myImageView.getHeight()/2;
int centerXOfImageOnScreen=myImageView.getLeft()+centerXOnImage;
int centerYOfImageOnScreen=myImageView.getTop()+centerYOnImage;
You can get the top-left corner coordinates using:
ImageView iv = (ImageView)findViewById(R.id.image_view);
Rect rect = iv.getDrawable().getRect();
int xOffset = rect.left;
int yOffset = rect.top;
Based on height/2 and width/2 you can establish the center of your ImageView .
Addition to Chandan's answer,
say we are using the same code:
int centerXOnImage=myImageView.getWidth()/2;
int centerYOnImage=myImageView.getHeight()/2;
int centerXOfImageOnScreen=myImageView.getLeft()+centerXOnImage;
int centerYOfImageOnScreen=myImageView.getTop()+centerYOnImage;
if your myImageView.getWidth() is returning 0, you might want to do a little bit of modification:
myImageView.measure(0,0);
int centerXOnImage=myImageView.getMeasuredWidth()/2;
int centerYOnImage=myImageView.getMeasuredHeight()/2;
Notice, you might want to do this after myImageView is created in code and added to a root view.

How to have scrolling animation programmatically

I'm trying to implement scroll animation for gallery programmatically.
Tried with setSelection(int pos, Boolean animate) and it's not working.
Is there anyway to override setSelection() method.
Just now I have got this problem. I was need to move just one element of the gallery, so the best solution to me was to emulate key down event
myGallery.onKeyDown(KeyEvent.KEYCODE_DPAD_RIGHT, null);
or
myGallery.onKeyDown(KeyEvent.KEYCODE_DPAD_LEFT, null);
Gallery.setSelection(int position, boolean animate);
Refer below URL:
http://groups.google.com/group/android-developers/browse_thread/thread/9140fd6af3061cdf/7f89e53ae53e455b?lnk=gst&q=setselection#7f89e53ae53e455b
Soln:
If you're still looking, I have two possible solutions for you, both
slightly unpleasant:
(1) You can make the gallery do a fling with a chosen velocity, thus:
myGallery.onFling(null, null, velocity, 0);
By tweaking the velocity, you can set up values to move the selection
by one or two in either direction. As the Gallery self-centers, you do
not need to get the destination exactly right.
(2) As the Gallery source is available, you can modify it in order to
implement your own Gallery. It doesn't look as though you need to add
much code to be able to control a fling so as to end at your chosen
selection.
I thought I was going to have to do (2), but found I could get away
with (1) for my problem.
Based on Kurru's excellent thinking of simulating clicking next or previous view.
//scroll forward or backward
private void scroll(int type){
View selectedV = mG.getSelectedView();
int idx = mG.indexOfChild(selectedV);
switch(type){
case FORWARD:
default:
if(idx<mG.getChildCount()-1)
idx++;
break;
case BACKWARD:
if(idx>0)
idx--;
break;
}
//now scrolled view's child idx in gallery is gotten
View nextView = mG.getChildAt(idx);
//(x,y) in scrolled view is gotten
int x = nextView.getLeft()+nextView.getWidth()/2;
int y = nextView.getTop()+nextView.getHeight()/2;
String out = String.format("x=%d, y=%d", x, y);
Log.i(TAG+".scroll", out);
//Kurru's simulating clicking view
MotionEvent event = MotionEvent.obtain(100, 100, MotionEvent.ACTION_DOWN, x, y, 0);
mG.onDown(event);
boolean res = mG.onSingleTapUp(null);
Log.i(TAG+".scroll", "onSingleTapUp return =" + res);
}
I was looking through the Gallery source to see if I could get this feature. It looks like something is possible with this code. However I gave up before I could get it working. It seems like I wasn't passing in the correct coordinates so res always returned false. Would return true if it worked.
Just posting this here in-case someone else wants to give a go at fixing it! (Please post your solution if you manage it!)
Rect rect = new Rect();
gallery.getHitRect(rect);
int x = rect.centerX()+getWindowManager().getDefaultDisplay().getWidth();
int y = rect.centerY();
MotionEvent event = MotionEvent.obtain(100, 100, MotionEvent.ACTION_DOWN, x, y, 0);
timesGallery.onDown(event);
boolean res = timesGallery.onSingleTapUp(null);
I made little change in code given by "Kurru". this is working now
Rect rect = new Rect();
gallery.getHitRect(rect);
int width = Math.abs(rect.width());
if(!isForwardScroll){
width = width * -1;
}
int x = rect.centerX()+width/2;
int y = rect.centerY();
MotionEvent event = MotionEvent.obtain(100, 100, MotionEvent.ACTION_DOWN, x, y, 0);
gallery.onDown(event);
boolean res = gallery.onSingleTapUp(null);

How to animate text over another View in Android?

I'm trying to animate some text 'zooming out' on top of another view. My code looks something like:
class BoardView extends View {
private TextView animText;
...
private void animText(String text, int color, int xBlocks, int yBlocks) {
animText.setText(text);
animText.setTextColor(color);
animText.setVisibility(View.VISIBLE);
final int x = BOARD_X_OFFSET + xBlocks * xBlockSize;
final int y = BOARD_Y_OFFSET + yBlocks * yBlockSize;
final float SCALE_FROM = (float) 0.25;
final float SCALE_TO = (float) 5.0;
ScaleAnimation anim = new ScaleAnimation(SCALE_FROM, SCALE_TO, SCALE_FROM, SCALE_TO, x, y);
anim.setDuration(500);
animText.setAnimation(anim);
this.setAnimation(null);
startAnimation(anim);
}
}
with animText being invoked in the onDraw() routine of the BoardView. What I'm seeing, however, is the board zooming out, not the text, despite the above calls to setAnimation().
I've looked in the main android docs and at one other example. Even pointers in the right direction would be helpful.
Well, I'm glad I'm not the only one who had a difficult time finding the very subtle bug in the above. The bug is:
startAnimation(anim);
which isn't too obvious until you expand it into:
this.startAnimation(anim);
at which point it's clear why the outer view (ie. 'this') is animating as well as the text.

Categories

Resources