Android: how to check if two rotated views overlap - android

i have a button which rotates in the middle of the screen using an ObjectAnimator and another button (which will be a square or a circle) moving back and forth, which sometimes does overlap on the first.
I need to know when the first button is covered by the second one, however the first button does rotate, so i can't just compare the two rectangles.
Does anybody know a solution?
edit
I've been trying pturner's solution but there have been a few issues that i can't fix anyhow:
The rotating button's rectangle's values seem to be generated from the origin of the axis, rather than the origin of the button, thus the moving button will believe he's intersecting the rotating button in the top-left side of the screen.
When the rotating button rotates, the rectangles' values will eventually invert, becoming negative and thus flipping left/right and top/bottom. As a result at certain angles the moving button believes to always be overlapping, while at some other it believes to never overlap.
I really have no clue how to fix those issues, i'll just leave this question here hoping for someone to know a solution.

I think you should be able to get the rects for both views, and then transform them with the matrix, something along the lines of:
Matrix matrix1 = button1.getMatrix();
Rect box1 = new Rect();
button1.getDrawingRect(box1);
Rectf boxf1 = new RectF(box1);
matrix1.mapRect(boxf1);
Matrix matrix2 = button2.getMatrix();
Rect box2 = new Rect();
button2.getDrawingRect(box2);
Rectf boxf2 = new RectF(box2);
matrix2.mapRect(boxf2);
boolean intersect = boxf1.intersect(boxf2);

Related

TranslateAnimation not moving view to correct place

I have two ImageViews inside a constraint layout. One on top and one on bottom. I want to move the bottom one onto the top one. Of course I know it doesn't change it's actual position which I am ok with. When I use TranslateAnimation to move to the specified coordinates the image goes down and to the right instead of moving up and to the right. Also when it moves to the right it is slightly off. I can use view.animate().y(getTop).x(getLeft); and it moves the image into the correct position but then it is stuck there. I can't get it to move back to its original like it would if fillAfter was false.
First I get the destination location
float x = playerOneCard.getLeft();
float y = playerOneCard.getTop();
This code moves the card to the correct location but does not reset it after being moved. I need it to essentially move there, go back to it's original place, and repeat as many times as the button is pressed.
playerOneCardMove.animate().x(x).y(y);
This code moves the image but down and towards the right no where close to lining up with the desired destination.
TranslateAnimation translateAnimation = new
TranslateAnimation(Animation.ABSOLUTE,x,Animation.ABSOLUTE,y);
translateAnimation.setDuration(500);
translateAnimation.setFillAfter(false);
playerOneCardMove.startAnimation(translateAnimation);
Figured it out. Since I was going from the absolute position of the first image the top left of that image is 0,0. So it was moving accordingly. Instead I measured the distance from the top of the image on the bottom to the top of the image above it and then moved it according to distance. I did the same for both x and y coordinates.
float distanceY = Math.abs(playerOneCardMove.getTop() - playerOneCard.getTop());
float distanceX = Math.abs(playerOneCard.getLeft() - playerOneCardMove.getLeft());
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.ABSOLUTE,distanceX ,Animation.ABSOLUTE,(distanceY) - (distanceY*2));
translateAnimation.setDuration(1000);
translateAnimation.setFillAfter(false);
playerOneCardMove.startAnimation(translateAnimation);
Hope this helps someone else.

Android prevent views overlap on drag and drop

I am adding some ImageViews to a relative layout dynamically (on touch points)
Any ImageView has an OnTouchListener. In Action Move I move the ImageView(sth like Drag and Drop).
My problem is that ImageViews may overlap each other when they are moving. I want to prevent them from overlap in any way! (best is stop moving when collision happen)
Look at this image
All ImageViews are saved in a link list. I get the x & y of moving view and compare it with other views and if they had collision don't let them moving.
But I want that user can make them separate again. How can I do this work?
In brief when views collision happen I don't let them move any more but I want if the move was making them far from each other it happens.
Try this
Rect rc1 = new Rect();
imageView1.getDrawingRect(rc1);
Rect rc2 = new Rect();
imageView2.getDrawingRect(rc2);
if (Rect.intersects(rc1, rc2) {
// intersection is detected
// here is your method call
}

want to create a semi doughnut shape button clickable in a particular region

I want to create a semi doughnut shaped button which is only clickable in the region where it is visible and not in the the whole rectangular region.
http://i.stack.imgur.com/MKD45.png
I want clicking to affect only this blue region.
You can do this by grabbing the Bitmap representation of the Button, then testing the x/y pixel's alpha value.
To get the bitmap for a button:
Bitmap buttonBmp;
button.setDrawingCacheEnabled(true);
buttonBmp = Bitmap.createBitmap(button.getDrawingCache());
button.setDrawingCacheEnabled(false);
I'd recommend only doing this once, and saving the results, that way you're not creating a new bitmap every time you touch the button.
Then you override the Button's onTouchEvent so you have the local x/y where the user tapped. If the alpha in that spot is 0, you have a non-clickable area. It's not as simple as an onClickListener, but it should do the job.
This way you can use any arbitrary shape, not just a doughnut. Colors, textures, whatever.
I'm not entirely sure on this but I think this scheme would work. Create an image view in your layout to display the picture and make it clickable via an onTouchEvent. This way you can get the coordinates of the click. Check to make sure that the click is within the inner and outer radii and if it is, do the given response.
Here are a few calculations that will need:
Center of circle
-Assuming the center is the very bottom of the image, this will look something like this(not necessarily exact methods)
centerX = img.getX() + img.getWidth()/2;
centerY = img.getY() + img.getHeight()/2;
Remember that screen coordinates go from top to bottom and from left to right.
Find the distance away from the center where the click occurred
Dx = click.getX() - centerX;
Dy = click.getY() - centerY;
D = Math.sqrt(Dx^2 + Dy^2);
Then all you need is to check if the distance is within the radii(not sure how to get the exact radii here, may just need to guess and check. An alternative may be that the top of the semicircle is the top of the picture and then the max height with be the outer radius.)
if(D<=outerR && D>=innerR)
respond();

Touch event for visible part of the Image

I need to apply click/touch events for only visible part of the View. Say for example a image of size 200X200. Apart from center 50X50, remaining part is transparent. I want to get touch events only for that 50X50 visible part Not on remaining transparent part.
In above image (its single image), only inner Diamond has got visible part. Apart from that Diamond is transparent area. So, if I touch Diamond then only I want to do something else ignore.
Edit :
Rachita's link helped me. I gone through that link and got idea how can I implement. But I could not understand some constants like 320, 240 etc while creating Points. In my case, I know the Diamond (in above image) x and y Ponits (hard coded values asctually). So, using those how can I determine, whether I touched inside Diamond or outside?
my Diamond points are as below
pointA = new Point(0, 183);
pointB = new Point(183, 0);
pointC = new Point(366, 183);
pointD = new Point(183, 366);
Edit :
Finally got solution from Luksprog. Its based on checking touched point pixel color. If color is 0 means, you touched transparent layer else you touched some colored part of the image. Simple, but very effective. Have a look at it here.
AFAIK you can not implement this with onclick listener or my any other direct way .You will have to use onTouchListener .
Firstly set your view dynamically at a specific (x,y) position using this How can I dynamically set the position of view in Android?
Calculate the region your diamond will occupy (you should khow the size of image inorder to calculate area of diamond)
3.Trigger a action in onTouchListener only when x, y fall in the required region. Use How to get the Touch position in android?
check this link to calculate if a given point lies in the required square
EDIT
To understand the coordinate system of android refer to this link How do android screen coordinates work?
Display mdisp = getWindowManager().getDefaultDisplay();
int maxX= mdisp.getWidth();
int maxY= mdisp.getHeight();
(x,y) :-
1) (0,0) is top left corner.
2) (maxX,0) is top right corner
3) (0,maxY) is bottom left corner
4) (maxX,maxY) is bottom right corner
here maxX and maxY are screen maximum height and width in pixels, which we have retrieved in above given code.
Remember if you want to support multiple devices with different screen sizes,make sure you use a relative value for x,y ie some ratio of screen height or width ,as different devices have different ppi
Check if touched point lies in the required polygon
I thinks these link might help you determining if the point touched (you can get x,y from onTouch event eg.event.getX()) lies in the required polygon whose points you have mentioned in the question . determine if a given point is inside the polygon and How can I determine whether a 2D Point is within a Polygon?

Rotating android view without affecting adjacent views

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

Categories

Resources