Center of the view after rotation or scale - android

I am trying to find the center of a view. For non-rotated view the value is correct, but for rotated view it's not correct as the centre(0,0) is rotating. In the case of scaling the width and height is keep constant even after zooming
I am using the following formula to calculate the center.
int[] location = new int[2];
childView.getLocationOnScreen(location);
int xLocation = location[0] + childView.getWidth() / 2;
int yLocation = location[1] + childView.getHeight() / 2
from getGlobalVisibleRect i get the rect of visible part only

https://developer.android.com/reference/android/view/View#getHitRect(android.graphics.Rect)
This method will return you Rect(considering rotation and scale) within its parent view

Related

How to vertically center a scaled View?

I'm trying to vertically center a rotated and scaled View. It doesn't seem to matter if it is rotated or not (if I keep the scale at 1.0 and rotate the view, and change the x position of the view by using setX it works as expected).
I know the center of my container, and I also know the width of the rectangle that holds the View in the container.
I am setting X of the View to be: the middle of the container - view/2.
This works if I don't scale the view up or down, however if I scale the image up the image doesn't appear in the center, it is always off a noticeable amount.
// Get center of container
val rect = Rect()
containerView.getHitRect(rect)
val width = rect.right - rect.left
val centerContainerView = rect.left + width/2
// At this point assume myView is rotated and scaled up (using any one of the many translate, scale, rotate on touch libraries)
val viewRect = Rect()
myView.getHitRect(viewRect)
val viewWidth = viewRect.right - viewRect.left
val newX = centerContainerView - viewWidth/2
// Tap a button and run the below to center myView
myView.x = newX.toFloat()
SetX

how to get bounds of a scaled view?

It seems that setScaleX or setScaleY don't actually change left,top,right,bottom properties. getX and getY remain unchanged too.
So if I scale a view whats the easiest way to get 4 corner coordinates of the newly scaled view?
I tried getHitRect but that doesn't give me the right answer. I am trying to avoid manually calculating the new bounds based on existing transformations (rotation and scale with pivots factored in).
After exploring the view api, it looks like there is no direct API method that does this.
However you can easily get the new points by grabbing the transform matrix of the view and using that to get the new bounds.
Something like this:
Matrix m = view.getMatrix();
Rect bbox = new Rect();
view.getDrawingRect(bbox);
m.mapRect(bbox);
If you want to operate on (x,y) coordiantes directly there is a matrix.mapPoints that will achieve the same result.
I believe if you get the width and height and multiply it by the scales, you'll get the scaled width and height.
int scaledWidth = getWidth() * getScaleX();
int scaledHeight = getHeight() * getScaleY();
int newLeft = getLeft() + (scaledWidth / 2);
int newRight = newLeft + scaledWidth;
int newTop = getTop() + (scaledHeight / 2);
int newBottom = newTop + scaledHeight;
This is assuming that you scaled with a pivot x and y at the center of the view. Things gets far more complicated if you have pivots in strange areas.

How to do hit test on a rotated image in Android?

I am trying to do hit test on a rotated image object drawn on the canvas in surface view.
When image is not rotate we can directly use left, top , width and height as boundaries to check whether the point lies within image rectangle. But how to do it when the object is rotated to some angle?
I am using: canvas.rotate(angle, pivotX ,pivotY); to draw the rotated image.
I could not get the rotated left and top of the image object. I tried to take original left and top of the image and when i tap on the screen i rotate the touch point back with same angle using:
angledTouchX = (float) (eventX * Math.cos(-objectAngle) - eventY * Math.sin(-objectAngle));
angledTouchY = (float) (eventY * Math.sin(-objectAngle) + eventX * Math.cos(-objectAngle));
It does not work because it rotates the point wrt (0,0), but i want it wrt center of the image object.
Was working on similar problem. In my case, I want to do a hottest between touchpoint and rotated and scaled view. So I transform touch point co-ordinate system according to view's rotation and check if its inside non-rotated view boundary or not.
Step
Get touch point in screen co-ordinate system which received from event.getRawX() and event.getRawY()
Target view location in screen location which received from
int location[] = new int[2];
view.getLocationOnScreen(location);
int viewX = location[0];
int viewY = location[1];
Create vector as if view origin is the space origin
float[] vec = new float[2];
vec[0] = event.getRawX() - viewX;
vec[1] = event.getRawY() - viewY;
Rotate the vector
Matrix matrix = new Matrix();
matrix.setRotate(-1 * view.getRotation());
matrix.mapVectors(vec);
Change rotated vector to screen space
vec[0] = vec[0] + viewX;
vec[1] = vec[1] + viewY;
Check if rotated touch co-ordinate is in view unrotated boundary
if(( vec[0] > viewX
&& vec[0] < (viewX + (view.getWidth() * view.getScaleX()) ))
&&( vec[1] > viewY
&& vec[1] < (viewY + (view.getHeight() * view.getScaleY()) ))){
isPointInTextView = true;
} else {
isPointInTextView = false;
}
You need to work with it mathematically. the best way to do is before you rotating the canvas change the position by width/2, height/2. Then apply rotation, finally move back to the previous location by width/2, height/2. Then your picture will be always rotated from the center. But still after rotating your new image will have a new size which fits as a rectagle align to screen sides.

How to get the X Y coordinates and pixel size of a TextView?

Given a TextView, is it possible to know at runtime the X and Y coordinates of where it is drawn?
Is it also possible to know the size (width/length) in pixels?
There are getLeft(), getTop(), getWidth(), getHeight() methods for a view, it works for textView too. for more information , see the following link...
getLeft() and getTop() will return you the starting x,y co-ordinates.
http://developer.android.com/reference/android/view/View.html
Coordinates relative to parent
int x = textView.getLeft();
int y = textView.getTop();
Absolute coordinates
int[] location = new int[2];
textView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
See this answer for more.
Pixel size
int width = textView.getWidth();
int height = textView.getHeight();
Notes
If you are getting (0,0) it could be because you are getting the relative coordinates related to the parent layout (and it is sitting in the top left corner of the parent). It could also be because you are trying to get the coordinates before the view has been laid out (for example, in onCreate()).

Scrollable ImageView Android Problem (overscrolling)

I got my image to at least SCROLL, but I don't want it to scroll past the image itself. I have variables called maxLeft, maxRight, etc that I have that I currently just set to
ImageView img = (ImageView)findViewById(R.id.mapimg);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int maxX = (int)????;
int maxY = (int)????;
// set scroll limits
final int maxLeft = (maxX * -1);
final int maxRight = maxX;
final int maxTop = (maxY * -1);
final int maxBottom = maxY;
I've been messing around with what I could in place of the question marks I put there, but I seem to be stuck, especially when I try on different emulators. Any help would really be appreciated! Thanks
If I understand your question correctly, you want to extend ImageView to add scrolling. If that's the case, you don't want to use getWindowmanager() as that returns the dimensions of the entire screen (including the title bar). Rather, you want to extend ImageView and get the view's dimensions from onMeasure. You can check out my answer here where I added zoom functionality and panning to ImageView.
I used setImageMatrix and postTranslate to set a matrix equal to the image and move it. To track the image's location, I used the following:
float f[] = new float[9];
matrix.getValues(m); //see matrix documentation. inserts matrix values into f.
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
Float x and y will track the top left corner of the image. Make sure if the next event will cause the image to scroll out of bounds, you adjust postTranslate to equal the border of the image. The answer i linked above should give you a good place to start, and if you also want zoom functionality, then you're in luck, because you don't have to do any additional work.

Categories

Resources