Rotating android view without affecting adjacent views - android

I'm rotating a view containing an arrow in my app using the Matrix class. However, the arrow doesn't rotate around its center but moves a bit horizontally and vertically when rotating. I've experimented with margins and padding but without success.
Any hints much appreciated.

The setRotate method in Matrix defaults to the (0,0) point of the view, which is the top left corner. You can set the point you want to rotate around by using the setRotate(float angle, float px, float py) method in the Matrix class. The x and y parameters are local to the view so you can get the center point from the bounds of the view or from getWidth and getHeight.

I think the translation works as you expect. It is the way you draw the resulting image which leads to imprecision. I have just answered a similar question Android problem with Image Rotate and Matrix

Related

What is programmatically equivalent to android:layout_centerInParent="true" of RelativeLayout?

I place an ImageView of a pin in the center of the layout by using android:layout_centerInParent="true" in my RelativaLayout XML file.
Now I wish to draw the green dot at the same position as the pin on the canvas.
NOTE: the green dot is NOT a view. It is drawn on canvas by canvas.drawCircle();
That is, I have to programmatically get the coordinates of the pin.
So how can I get the coordinates of android:layout_centerInParent="true" with codes?
My guess is
layoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, 1);
You can get layoutParams by relativeLayout.getLayoutParams(), and don't forget to setLayoutParams back when you're done modifying it.
To get the width and height of the parent you can do this.
RelativeLayout parent = (RelativeLayout) findViewById(R.id.yourRelativeLayout);
int width = parent.getWidth();
int height = parent.getHeight();
Then you can divide these numbers by 2 and set that to as your green dot's coordinates and it should appear in the middle of your screen. For this to work your canvas size has to be the same as the relative layout.
But beware, you need to call getWidth() and getHeight() methods after the activity has been created, else you will end up getting zero. See this answer
So, the canvas you are drawing to is in a view that is contained by the RelativeLayout, but you want to draw the dot at the center of the RelativeLayout?
Yes, that is exactly what I am trying to do!
Assuming the canvas view is a direct child of the RealtiveLayout, this should work.
You can get the layout's center by using getWidth() / 2 and getHeight() / 2 on the layout as others mentioned. However, you also have to figure out where the origin of the canvas is. For this you can just use getLeft() and getTop() on the canvas view. Then you just subtract the center x from left, and center y from top to get your final spot.
Example:
Assume each grid line is 1. The RelativeLayout is the large black rectangle, and the Canvas view is the blue one. The center dot's coordinates are 4,6. Using left/top, you get 1,4 for the canvas origin(red dot). Subtract, and you get 3,2, which are the local canvas coordinates for the green dot.
Drawing the dot in the center of the canvas should just be a matter of dividing the width and height of the view by two. If you want it to be at the base of the pin (as opposed to the true center), then just add half the height of the pin to the circle's y value.

Collision detection with rotated sprites, how to get correct bounding Rect?

I am currently creating an android game and implemented collision detection a while back. I am simply drawing a Rect around sprites using their position, width and height and seeing if they intersect other Rects. However, my sprites now rotate depending on their trajectory, but I cannot find how to rotate the Rect so the bound is correct. Any suggestions?
Thanks
Andy
Rect objects are usually axis-aligned, and so they only need 4 values: top, left, bottom, right.
If you want to rotate your rectangle, you'll need to convert it to eight values representing the co-ordinate of each vertex.
You can easily calculate the centre value by averaging all the x- and y-values.
Then it's just basic maths. Here's something from StackOverflow:
Rotating a point about another point (2D)
Your eight values, or four corners are (assuming counter-clockwise from the top right):
v0 : (right, top)
v1 : (left, top)
v2 : (left, bottom)
v3 : (right, bottom)
Create your own rectangle object to cope with this, and compute intersections etc.
Note that I've talked about how to rotate the rectangle's vertices. If you still want a bounding box, this is normally still considered to be axis-aligned, so you could take the max and min of the rotated vertices and construct a new (larger) rectangle. That might not be what you want though.

Rectangle Coordinates With Respect To The Rotation Angle

I am trying to create custom components in Android using Surfaceview and canvas drawing. The components are re-sizable and rotatable by touching. Consider creating an image view its Top,Right,Bottom, and Left edges are scalable by touching and dragging the required edge. I am using RectF to keep the bounds of the component, For rotation I am using canvas.rotate(angle, bounds.centerX(),bounds.centerY()) method. The problem is while resizing top edge, the Let , Right and Bottom edges should be fixed, and I cannot able to fix it if the rotation angle is other than 0 degrees. I need a math solution to find out the x,y coordinates of a rotated rectangle with respect to the actual rectangle's bounds.
I can explain it with the help of some images.
The following Figure displays two rectangles whose bounds are also known and displayed in respective colors. Consider the Green Rect as the components initial bounds, ie. rotated by -45 Degrees, Center is (10,10). Now going to re-size the Top edge of the rectangle and displayed in next Figure 2.
From the Figure 2 it is understood that the Y position is reduced to 4 from 6. The rotated Rectangle is also shown in pink color. Remember I am doing resizing while the component is at rotation angle -45 degrees, so while dragging Top Edge rectangle's Left, Right and Bottom positions should not be changed. So the Figure 2's Pink Rectangle should have Left, Right, and Bottom coordinates same as Figure 1's Green Rectangle. Comparison of the obtained and expected rectangle is shown in Figure 3.
In Figure 3 the yellow color rectangle is the Expected/Required out put. The obtained rectangle Pink color is shifted upwards compared to the Green rotated rectangle and that is varying depends on the Angle of rotation.
I have rotation angle = -45 degree
Bounds of Actual (Not re-sized) rectangle.
Bounds of Actual (Not re-sized) rectangle at Rotation = -45 degrees.
Bounds of Re-sized rectangle.
Bounds of Re-sized rectangle at Rotation = -45 degrees.
How do I calculate the Bounds / Center of the Yellow Rectangle. So that I can implement the resizing of my components correctly? Let me know is there is any mathematics that can be applied?
The required points / coordinates are marked as Red color circles in Figure 3.
The key is this: "I cannot able to fix it if the rotation angle is other than 0 degrees."
Let's say your rectangle is rotated 10 degrees.
1) rotate the mouse coordinate around some point on the screen by -10 degrees
2) rotate the center of the rectangle by -10 degrees
... now you reduced the problem to a rectangle that is at 0 degrees. The rectangle moved, yes, the mouse moved, but they are relative to each other as they should be.
3) Now do the the rectangle manipulation. The rectangle center will shift.
4) Rotate the new rectangle center by 10 degrees
This way you do not have to think about it and you are always working in un-rotated coordinates.
Point at [x, y] rotated by angle a will end up at [x*cos(a) - y*sin(a), x*sin(a) + y*cos(a)]
All colors in this answer refer to your figure 3.
If I understood your question correctly, you know how to compute all the details about the pink rectangle as well as the green rectangle. So simply take the difference between one corner of the pink rectangle and the corresponding corner of the green rectangle. Adding that difference (a two-element vector, i.e. x and y difference separately) to the center of the pink rectangle will give you the desired center of the yellow triangle.
If you need to compute the dimensions of the pink rectangle as well, you might want to do so in the unrotated coordinate system. Take your green rectangle together with the coordinates of the point towards which you want to extend the rectangle, and rotate them back by +45°. Then you can extend the height of the rectangle to the value you desire, which will give you the blue rectangle, and from that by rotation the pink rectangle.

Android - Set focus on a circle that I have drawn in my onDraw method

Android Question.
I have made a custom ImageView class and inside it I have an onDraw method which will draw a circle on particular pixels (using canvas). When I use this custom imageview and open up my image I would like to set the focus on the circle that I have drawn (e.g like google maps do with your current location. The focus is set to your current point)
What the map server does on google is deliver a customized set of tiles so that the center is displayed properly, the newer version is of course vector based so they simply draw the view so it's centered where they want it.
Without knowing the details of your application you probably need
Create your own container class, probably FrameLayout
public class myMapFrameLayout extends FrameLayout {
The override either onDraw or onDispatchDraw so that you can layout your tile appropriately
Figure out where to draw your bitmap so that the x,y you need will be in the center of the screen, then draw the other tiles that you need to fill in the blank space at the coordinates required dependent on which way the tile was moved to get centered
Think of a virtual screen that is larger than the actual screen with tiles all around it that are the same size
1 2 3
4 X 5
6 7 8
Assuming that X is the size of the display and represents the current tile you need to figure out which way to move the tile, and which other tiles 1,2,3,4,5,6,7 or 8 you need to fill in the empty space caused by move
If you had to draw the tile +x from 0,0 you need some of tile 4, drawing +y from 0,0 means some of 2 and both mean 1,2,4 are all needed and so on, so figure out the combinations and load the tiles you need, and figure out the drawing positions of each. That would give you your new virtual tile with the center displayed.
That's about as efficient as you can get I think with a bitmap drawing method on the client side.
UPDATE
Since your comment indicates you have only one very large image this is going to be a bit of a problem if the x,y you need as anything closer to the edges than the size of the display
None the less you can still draw the image where you need it, just measure the screen and draw the bitmap with the target x,y in the center
So if the screen was 500x500 and your image was 5000x5000 and the center was at position x=1000 y=1000 then
drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)
where source rectangle would be 1000-250,1000-250,500,500 and dst rectangle would be 0,0,500,500
The 250 is the center x and center y of the display, 1000 are the target x/y coordinates, and 500 is the size of display.
Again, with targets that are at the edges you are going to have a blank polygon in your screen since you dont have an infinite map tile
Alternatively you could oversize your framelayout using layoutparams and just translate the canvas in the x and y to get the canvas centered to the x,y you need using similar calcs which may be more performant, not really sure
Keep in mind you are going to be using a lot of memory if your image is really big

3D rotation while object being translated

I've been playing with Android animation framework and I found the following 3D rotation sample code:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Transition3d.html
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/animation/Rotate3dAnimation.html
It does pretty much what I want but I want the ImageView to rotate while it's being translated from point A to point B and the it should rotate along it's own center(which is moving) instead of the center of the container of screen.
Does anyone know how to do that?
-Rachel
Well it's pretty close to what you posted. Essentially you're multiplying the rotational matrix by the translation matrix. That's essentially what happens under the covers. Android hides that detail from you with it's API:
Matrix matrix = transformation.getMatrix();
matrix.rotate( rotateX, rotateY );
matrix.postTranslate( transX, transY );
Rotate first then translate will rotate the image around it's own axis first before translating it.

Categories

Resources