I trying to get x,y for any object inside the layout but I got this values when object at end corner of the screen :
Object X : 266
Object Y : 361
Screen Width : 320
Screen Height: 480
how can I know where is the object exactly for the screen? (end,top,left,center).
Hope this helps..
public Rect locateView(View view) {
Rect loc = new Rect();
int[] location = new int[2];
if (view == null) {
return loc;
}
view.getLocationOnScreen(location);
loc.left = location[0];
loc.top = location[1];
loc.right = loc.left + view.getWidth();
loc.bottom = loc.top + view.getHeight();
return loc;
}
And I used the method this way:
Rect r = TVGridUtils.locateView(activity.findViewById(R.id.imageview));
float touchX=r.left+((r.right-r.left)/2);
float touchY=(r.bottom);
Note: I had to get the middle point of the imageview which i touched
I think you need to add the width and height of the objects to x and y values
To know where is the object exactly for the screen
X= 0,Y= 0 TOP LEFT
X= screenWidth-objectWidth,Y= 0 TOP RIGHT
X= 0,Y= screenHeight-objectHeight BOTTOM LEFT
X= screenWidth-objectWidth,Y= screenHeight-objectHeight BOTTOM RIGHT
Button b;
int x1 = b.getX();
int x2 = x1 + b.getWidth();
int y1 = b.getY();
int y2 = y1 + b.getHeight();
Related
I'm trying to recognize if the (x,y) of my finger is touching any part of the triangle object.
This is how I draw the triangle
public void drawTriangle(Canvas canvas, Paint paint, int x, int y, int width) {
int halfWidth = width / 2;
Path path = new Path();
path.moveTo(x, y - halfWidth); // Top
path.lineTo(x - halfWidth, y + halfWidth); // Bottom left
path.lineTo(x + halfWidth, y + halfWidth); // Bottom right
path.lineTo(x, y - halfWidth); // Back to Top
path.close();
canvas.drawPath(path, paint);
}
This is how I draw to the screen + examples of how I recognize other shapes like square and circle:
public boolean onTouchEvent(MotionEvent event) {
int X = (int) event.getX();
int Y = (int) event.getY();
int eventaction = event.getAction();
switch (eventaction) {
/*
case MotionEvent.ACTION_DOWN:
Toast.makeText(this, "ACTION_DOWN AT COORDS "+"X: "+X+" Y: "+Y, Toast.LENGTH_SHORT).show();
isTouch = true;
break;
*/
case MotionEvent.ACTION_MOVE:
{
int s = triangle.getY() * triangle.getWidth()/ triangle.getY()-triangle.getWidth()/2;
if(X>=circle.getX()-circle.getRadius()&&X<=circle.getX()+circle.getRadius()
&&Y>=circle.getY()-circle.getRadius()&&Y<=circle.getY()+circle.getRadius()) {
circle.setX(X);
circle.setY(Y);
//square.setX(X);
//square.setY(Y);
}
if(X < square.getX() + square.getWidth() && X + square.getWidth() > square.getX() &&
Y < square.getY() + square.getHeight() && Y + square.getHeight() > square.getY())
{
square.setX(X);
square.setY(Y);
}
if(//triangle help)
{
triangle.setX(X);
triangle.setY(Y);
}
break;
}
}
return true;
}
Source link of pseudocode solution.
There are multiple ways to check if the point is in or out of a triangle.
Let's say that each of the vertices of a triangle has inner and outer sides. Inner is the one that is inside of a triangle, outer is therefore outside of a triangle.
To check if a point is inside of a triangle we can check if the point is on the inner side of each triangle vertex.
Note: this solution might require some minor changes from you as I do not know the exact structure of your triangle class.
public boolean onTouchEvent(MotionEvent event) {
int X = (int) event.getX();
int Y = (int) event.getY();
int eventaction = event.getAction();
switch (eventaction) {
case MotionEvent.ACTION_MOVE:
{
...
int halfWidth = triangle.getWidth()/2;
Pair<Integer, Integer> v1 = new Pair(triangle.getX(), triangle.getY() - halfWidth);
Pair<Integer, Integer> v2 = new Pair(triangle.getX() - halfWidth, triangle.getY() + haldWidth);
Pair<Integer, Integer> v3 = new Pair(triangle.getX() + halfWidth, triangle.getY() + halfWidth);
if (isPointInTriangle(x, y, v1, v2, v3)) {
// point is inside of a triangle
}
break;
}
}
return true;
}
private int sign(int x, int y, Pair<Integer, Integer> vertex1, Pair<Integer, Integer> vertex2) {
return (x - vertex2.first) * (vertex1.second - vertex2.second) - (vertex1.first - vertex2.first) * (y - vertex2.second);
}
private boolean isPointInTriangle(int x, int y, Pair<Integer, Integer> vertex1, Pair<Integer, Integer> vertex2, Pair<Integer, Integer> vertex3)
{
int r1 = sign(x, y, vertex1, vertex2);
int r2 = sign(x, y, vertex2, vertex3);
int r3 = sign(x, y, vertex3, vertex1);
boolean hasNegative = (r1 < 0) || (r2 < 0) || (r3 < 0);
boolean hasPositive = (r1 > 0) || (r2 > 0) || (r3 > 0);
return !(hasNegative && hasPositive);
}
Here is what I would do to recognize them:
1- Every shape I draw will have its coordinates saved in a list (example: a circle has a center and a radius). These coordinates can help you to decide if a given touch coordinate is touching a shape. You can use a list by shape if you want to know the type of the shape.
2- Whenever you will touch a portion of the canvas, you will get the coordinates of this touched part, then go through the saved shapes and check if the coordinates are on/in (sorry I am french speaking) the shape. So the thing now it that you will have to check the algorithms that will allow you to know when a coordinate/point is on/in a shape.
I have been trying for more than a week now, but I am not able to rotate the layout(Relative) properly based on the touch. I need to set the angle of rotation such that the layout rotates as I move the finger on the left bottom of the layout (which has a small image). Basically I am having a Relative layout which has a sticker image. I am able to drag and zoom the sticker(Image) by touching the respective corner of the layout but I am not able to rotate it properly. Can somebody help me to set the angle of rotation so that the whole layout can be rotated smoothly?
here is the code snippet
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
lastTouchedScaleXPosition = event.getX();
lastTouchedScaleYPosition = event.getY();
if(previousXPosition == 0 && previousYPosition == 0){
int[] viewLocation = new int[2];
v.getLocationOnScreen(viewLocation);
previousXPosition= viewLocation[0];
previousYPosition= viewLocation[1];
}
break;
}
case MotionEvent.ACTION_MOVE: {
currentTouchedXPosition = event.getX() - lastTouchedScaleXPosition;
currentTouchedYPosition = event.getY() - lastTouchedScaleYPosition;
currentXPosition = previousXPosition + currentTouchedXPosition;
currentYPosition = previousYPosition + currentTouchedYPosition;
RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.parent);
int w = mainLayout.getWidth();
int h = mainLayout.getHeight();
float center_x = 0;
float center_y = 0;
center_x += w/2;
center_y += h/2;
double tx = currentXPosition - center_x, ty = currentYPosition - center_y;
double t_length = Math.sqrt(tx*tx + ty*ty);
double a = Math.toDegrees(Math.acos(ty / t_length));
mainLayout.setRotation((float) a);
mainLayout.setTranslationX((w - h) / 2);
mainLayout.setTranslationY((h - w) / 2);
ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) mainLayout.getLayoutParams();
lp.height = w;
lp.width = h;
parent.setLayoutParams(lp);
previousXPosition = currentXPosition;
previousYPosition = currentYPosition;
break;
}
}
return true;
}
`
Tried many things but didnot get the desired result.This link helped me to solve the issue.
rotate and resize the image view with single finger in android
Source link https://github.com/ryanch741/android-view-rotate-zoom-single-finger
I am calculating the swipe area in android tab. Requirement is that when user swipes on the top 10% of the screen in tab a popup should come.
How can i achieve it by using the touch event of onFling();
Right now I am doing it like below, (arg0 and arg1 are Motion events)
int height = this.webview.getHeight();
float x = arg0.getRawX();
float y = arg0.getRawY();
float x2 = arg1.getRawX();
float y2 = arg1.getRawY();
if (x < 2000.00 && x2 < 2000.00 && y < 200.00 && y2 < 80.00) {
showPopUp();
}
But, I dont want to use the hardcoded values like 2000.00 or 80.00. Instead of this the swipe should be calculated based on the device height. Though this is working fine.
Any idea how to do it?
You can get the screen height via WindowManager
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
// This is the height of the screen
size.y;
You can then easily use that to determine if a swipe is in the top 10%.
Depending on where you're needing to calculate the height, you could cache this value in a member (in onResume() for an Activity) so that it gets updated when the config changes (device rotation, etc.)
int height = this.webview.getHeight();
int width = this.webview.getWidth();
float maxHeight = height*.10f; //10% of 1000 is 100
float maxWidth = width*.10f; //10% of 500 is 50
float x = arg0.getRawX();
float y = arg0.getRawY();
float x2 = arg1.getRawX();
float y2 = arg1.getRawY();
if (x > 0 && x2 < maxWidth && y > 0 && y2 < maxHeight) {
showPopUp();
}
I use this method to add a Sprite to the screen randomly.
private void addFace() {
Random rand = new Random();
float x = (int) mCamera.getHeight() + mBallTextureRegion.getHeight();
float minY = mBallTextureRegion.getHeight();
float maxY = (int)(mCamera.getWidth() - mBallTextureRegion.getWidth());
float rangeY = maxY - minY;
float y = rand.nextInt((int)rangeY) + minY;
this.mFaceCount++;
Log.e("Faces: ", "Face" + this.mFaceCount);
Sprite face = null;
Body body = null;
The only problem is i would like for the sprites to be added at the top of the screen(which is the camera) but instead they are added on the side of the screen.
Any suggestions on how to do this?
First of all, the (x,y) coordinates of an entity are on it's top left. So, minY should be 0, or you could just do:
float y = rand.nextFloat(maxY);
You don't need all of these (int) casts, you can delete them.
In order to make to position random, get a random X too:
float maxX = this.mCamera.getWidth() - this.mBallTextureRegion.getWidth();
float x = rand.nextFloat(maxX);
This should work.
On the android screen, the origin of the coordinate system is in the upper left corner.
(0,0)......(1,0)
(0,1)......(1,1)
So if you want something to always spawn at the top of the screen, then Y will need to be 0. Always. the X value can be anything from 0 to the width, randomly. This will place the object at the top, and randomly in the X (left-right) direction
Can I get a View's x and y position relative to the root layout of my Activity in Android?
The Android API already provides a method to achieve that.
Try this:
Rect offsetViewBounds = new Rect();
//returns the visible bounds
childView.getDrawingRect(offsetViewBounds);
// calculates the relative coordinates to the parent
parentViewGroup.offsetDescendantRectToMyCoords(childView, offsetViewBounds);
int relativeTop = offsetViewBounds.top;
int relativeLeft = offsetViewBounds.left;
Here is the doc
This is one solution, though since APIs change over time and there may be other ways of doing it, make sure to check the other answers. One claims to be faster, and another claims to be easier.
private int getRelativeLeft(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getLeft();
else
return myView.getLeft() + getRelativeLeft((View) myView.getParent());
}
private int getRelativeTop(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getTop();
else
return myView.getTop() + getRelativeTop((View) myView.getParent());
}
Let me know if that works.
It should recursively just add the top and left positions from each parent container.
You could also implement it with a Point if you wanted.
Please use view.getLocationOnScreen(int[] location); (see Javadocs). The answer is in the integer array (x = location[0] and y = location[1]).
View rootLayout = view.getRootView().findViewById(android.R.id.content);
int[] viewLocation = new int[2];
view.getLocationInWindow(viewLocation);
int[] rootLocation = new int[2];
rootLayout.getLocationInWindow(rootLocation);
int relativeLeft = viewLocation[0] - rootLocation[0];
int relativeTop = viewLocation[1] - rootLocation[1];
First I get the root layout then calculate the coordinates difference with the view.
You can also use the getLocationOnScreen() instead of getLocationInWindow().
No need to calculate it manually.
Just use getGlobalVisibleRect like so:
Rect myViewRect = new Rect();
myView.getGlobalVisibleRect(myViewRect);
float x = myViewRect.left;
float y = myViewRect.top;
Also note that for the centre coordinates, rather than something like:
...
float two = (float) 2
float cx = myViewRect.left + myView.getWidth() / two;
float cy = myViewRect.top + myView.getHeight() / two;
You can just do:
float cx = myViewRect.exactCenterX();
float cy = myViewRect.exactCenterY();
You can use `
view.getLocationOnScreen(int[] location)
;` to get location of your view correctly.
But there is a catch if you use it before layout has been inflated you will get wrong position.
Solution to this problem is adding ViewTreeObserver like this :-
Declare globally the array to store x y position of your view
int[] img_coordinates = new int[2];
and then add ViewTreeObserver on your parent layout to get callback for layout inflation and only then fetch position of view otherwise you will get wrong x y coordinates
// set a global layout listener which will be called when the layout pass is completed and the view is drawn
parentViewGroup.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
//Remove the listener before proceeding
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
parentViewGroup.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
parentViewGroup.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
// measure your views here
fab.getLocationOnScreen(img_coordinates);
}
}
);
and then use it like this
xposition = img_coordinates[0];
yposition = img_coordinates[1];
I wrote myself two utility methods that seem to work in most conditions, handling scroll, translation and scaling, but not rotation. I did this after trying to use offsetDescendantRectToMyCoords() in the framework, which had inconsistent accuracy. It worked in some cases but gave wrong results in others.
"point" is a float array with two elements (the x & y coordinates), "ancestor" is a viewgroup somewhere above the "descendant" in the tree hierarchy.
First a method that goes from descendant coordinates to ancestor:
public static void transformToAncestor(float[] point, final View ancestor, final View descendant) {
final float scrollX = descendant.getScrollX();
final float scrollY = descendant.getScrollY();
final float left = descendant.getLeft();
final float top = descendant.getTop();
final float px = descendant.getPivotX();
final float py = descendant.getPivotY();
final float tx = descendant.getTranslationX();
final float ty = descendant.getTranslationY();
final float sx = descendant.getScaleX();
final float sy = descendant.getScaleY();
point[0] = left + px + (point[0] - px) * sx + tx - scrollX;
point[1] = top + py + (point[1] - py) * sy + ty - scrollY;
ViewParent parent = descendant.getParent();
if (descendant != ancestor && parent != ancestor && parent instanceof View) {
transformToAncestor(point, ancestor, (View) parent);
}
}
Next the inverse, from ancestor to descendant:
public static void transformToDescendant(float[] point, final View ancestor, final View descendant) {
ViewParent parent = descendant.getParent();
if (descendant != ancestor && parent != ancestor && parent instanceof View) {
transformToDescendant(point, ancestor, (View) parent);
}
final float scrollX = descendant.getScrollX();
final float scrollY = descendant.getScrollY();
final float left = descendant.getLeft();
final float top = descendant.getTop();
final float px = descendant.getPivotX();
final float py = descendant.getPivotY();
final float tx = descendant.getTranslationX();
final float ty = descendant.getTranslationY();
final float sx = descendant.getScaleX();
final float sy = descendant.getScaleY();
point[0] = px + (point[0] + scrollX - left - tx - px) / sx;
point[1] = py + (point[1] + scrollY - top - ty - py) / sy;
}
Incase someone is still trying to figure this out. This is how you get the center X and Y of the view.
int pos[] = new int[2];
view.getLocationOnScreen(pos);
int centerX = pos[0] + view.getMeasuredWidth() / 2;
int centerY = pos[1] + view.getMeasuredHeight() / 2;
I just found the answer here
It says:
It is possible to retrieve the location of a view by invoking the methods getLeft() and getTop(). The former returns the left, or X, coordinate of the rectangle representing the view. The latter returns the top, or Y, coordinate of the rectangle representing the view. These methods both return the location of the view relative to its parent. For instance, when getLeft() returns 20, that means the view is located 20 pixels to the right of the left edge of its direct parent.
so use:
view.getLeft(); // to get the location of X from left to right
view.getRight()+; // to get the location of Y from right to left
You can use the following the get the difference between parent and the view you interested in:
private int getRelativeTop(View view) {
final View parent = (View) view.getParent();
int[] parentLocation = new int[2];
int[] viewLocation = new int[2];
view.getLocationOnScreen(viewLocation);
parent.getLocationOnScreen(parentLocation);
return viewLocation[1] - parentLocation[1];
}
Dont forget to call it after the view is drawn:
timeIndicator.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
final int relativeTop = getRelativeTop(timeIndicator);
});