Coordinate X& Y on Screen different size - android

I have a view and inside a viewpager with images. When I touch the view I display an image where I'm touching.
In the same time I send X and Y position in Firebase.
In another device, I get back those coordinates and display an image at those coordinates.
But the screen size of the tablets are differents, how can I show my image at the same position ? Because if I touch the middle screen of the first tablet, it showing an image en the right bottom of the other one
UPDATE
For user 1, when he touch the view a pointer/cursor is showing
v.animate()
.x(Math.round(event.getX()))
.y(Math.round(event.getY()))
.setDuration(0)
.start();
In the same time he sends coordinates to Firebase and the width and height of his screen.
Display display = getActivity().getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Map<String, Object> map = new HashMap<>();
map.put("x", Math.round(event.getX()));
map.put("y", Math.round(event.getY()));
map.put("sizeX", width);
map.put("sizeY", height);
mRefMyPos.updateChildren(map);
The user 2 has a listener and get back those data to display an imageView at the coordinates.
listenerRefCoordonate = mRefCoordonate.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
CoordonateModel coordinateModel = dataSnapshot.getValue(CoordonateModel.class);
if (coordinateModel == null){
//do something
mImageView.setVisibility(View.GONE);
} else {
final Float mScale = Math.min(1.0f * width / coordinateModel.getSizeX(), 1.0f * height / coordinateModel.getSizeY());
if (coordinateModel.getX() != null){
mImageView.setVisibility(View.VISIBLE);
mImageView.animate()
.x(Math.round(coordinateModel.getX() * mScale))
.y(Math.round(coordinateModel.getY() * mScale))
.setDuration(0)
.start();
}
}
}
#Override
public void onCancelled(DatabaseError firebaseError) {
}
});
Seems to be incorrect for example if I have an imageview with ABCDEFGHI.... (match_parent), if I try to show C, it showing E on the other device. Maybe my scale is incorrect ??
I tried to test if the scale is correct. When I touch the screen without displaying imageview where I'm touching but I'm listening what I'm writting on FireBase and displaying imageview with coordinates/with and height of screen device and do the scale and the when I'm displaying the imageview it showing where I'm touching so I guess the scale is correct
I will try to re explain my problem:
Tablet n1, 1024/768
Tablet n2, 1920/1200
Both are on a view full_screen with the same Imageview scale FitXY and match_parent
On the first tablet I'm touching the tail of the pig (Imageview), I'm sending X,Y position of the screen touch (Math.round(event.getX(), Math.round(event.getY()) and the width/height screen size of the tablet. The second tablet displaying (a cursor) around the tail of the pig but not at the exact position....
Can someone help me ?
User tablet 1 touching his screen (RED POINT where he's touching)
User tablet 2 listening X,Y position and draw where the user 1 is touching (RED POINT)
UPDATE 2
I changed and I calculate like this one on this post stackoverflow.com/a/21588683/5845928 I have what you said : tablet 1 the point is (258,230) and tablet 2 (484, 359). the problem seems to be the imageview. How can I solve it ?
** FIXED **
TABLET 2 receive x,y position and width and height of tablet 1.
hisWidth = coordinateModel.getSizeX();
hisHeight = coordinateModel.getSizeY();
float percent_width = Float.valueOf(coordinateModel.getX()) / hisWidth;
float percent_height = Float.valueOf(coordinateModel.getY()) / hisHeight;
float x = percent_width * mWidth;
float y = percent_height * mHeight;

Try to send also device width and height, so you could use them to calculate the exact (X,Y) in other devices

Related

Use x/y coordinates to set bounds of a moving particle

I have two bitmaps that I draw onto the center of a canvas:
One is only a background, it's a spirit level in top view which doesnt move. The second one is a bitmap looking like a "air bubble". When the user tilts the phone, the sensors read the tilt and the air bubble moves according to the sensor values along the x-axis. However, I need to make sure that the air bubble doesnt move too far, e.g out of the background-bitmap.
So I tried to which x coordinate the bubble can travel to,
before I have to set xPos = xPos -1 using trial and error
This works fine on my device.
To clarify: On my phone, the air bubble could move to the coordinate x = 50 from the middle of the screen. This would be the point, where the bitmap is at the very left of the background spirit level.
On a larger phone, the position x = 50 is too far left, and therefore looking like the air bubble travelled out of the water level.
Now I've tried following:
I calculated the area in % in which the air bubble can move. Let's say that
is 70% of the entire width of the bitmap. So I tried to calculate the two x boundary values:
leftBoundary = XmiddlePoint - (backgroundBitmap.getWidth() * 0.35);
rightBoundary = XmiddlePoint + (backgroundBitmap.getWidth() * 0.35);
...which doesnt work when testing with different screen sizes :(
Is it possible to compensate for different screen sizes and densities using absolute coordinates or do I have to rethink my idea?
If you need any information that I forgot about, please let me know. If this question has already been answered, I would appreciate a link :) Thanks in advance!
Edit:
I load my bitmaps like this:
private Bitmap backgroundBitmap;
private static final int BITMAP_WIDTH = 1898;
private static final int BITMAP_HEIGHT = 438;
public class SimulationView extends View implements SensorEventListener{
public SimulationView(Context context){
Bitmap map = BitmapFactory.decodeResource(getResources, R.mipmap.backgroundImage);
backgroundBitmap = Bitmap.createScaledBitmap(map, BITMAP_WIDTH, BITMAP_HEIGHT, true;
}
and draw it like this:
protected void onDraw(Canvas canvas){
canvas.drawBitmap(backgroundBitmap, XmiddlePoint - BITMAP_WIDTH / 2, YmiddlePont - BITMAP_HEIGHT / 2, null);
}
backgroundBitmap.getWidth() and getHeight() prints out the correct sizes.
Calculating like mentioned above would return following boundaries:
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;
//which prints out width = 2392
xMiddlePoint = width / 2;
// = 1196
leftBoundary = xMiddlePoint - (BITMAP.getWidth()* 0.35);
// = 531,7
However, when I use trial and error, the right x coordinate seems to be at around 700.
I've come across a great explanation on how to fix my issue here.
As user AgentKnopf explained, you have to scale coordinates or bitmaps like this:
X = (targetScreenWidth / defaultScreenWidth) * defaultXCoordinate
Y = (targetScreenHeight / defaultScreenHeight) * defaultYCoordinate
which, in my case, translates to:
int defaultScreenWidth = 1920;
int defaultXCoordinate = 333;
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
displayWidth = displayMetrics.widthPixels;
leftBoundary = (displayWidth / defaultScreenWidth) * defaultXCoordinates

android move image from one place to another place on different screen size and resolutions

I am new in android. I want to make ludo game. and I sets all things related to this game. but I want to move TOKEN from one place to another for different screens like (Nexus 6, Samsung Note 5, Moto G3, etc...). But issue is that for every screen size (Width x Height) are different. that's why I am not set proper x and y position on screen. I referenced screen Height and Width for taking next position (x and y) on screen to move TOKEN on screen. I am taking static image for Ludo Dashboard. That's why i am not getting how to move.
for example:
My Screen is as below,
from origin position to Home position :
In this situation, for every screens translation was changed. because i am taking reference screen Height and Width for move.
for that code is below,
DisplayMetrics displaymetrics = getResources().getDisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
this.constant.Height = displaymetrics.heightPixels;
this.constant.Width = displaymetrics.widthPixels;
private float getheight(float val) {
return (this.constant.Height * val) / 800;
}
private float getwidth(float val) {
return (this.constant.Width * val) / 480;
}
ObjectAnimator animTranslateY = ObjectAnimator.ofFloat(img,
"translationY", blue_1.getY() + getheight(67));
animTranslateY.setDuration(GameConstants.DURATION);
ObjectAnimator animTranslateX = ObjectAnimator.ofFloat(img,
"translationX", blue_1.getX() + getwidth(128));
animTranslateX.setDuration(GameConstants.DURATION);
AnimatorSet anim = new AnimatorSet();
anim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
anim.play(animTranslateX);
anim.play(animTranslateY);
anim.start();
from Home to Common Rout :
In this situation, its work fine. bt for different screen its moving differ.
So, my question is that How can i move and what should be reference for move image form one position to another position. I takes too many time for this. Please help me.
So, I tried to come up with a solution that uses simple unitary method to solve your problem. I am not sure if it works, I did not try it by coding it actually!
I am assuming that you have set the background static image to scale its size (width) to 100% of the screen, your static image is a square(usually a ludo board is). Also I am considering here that screenwidth is smaller than screenheight. If it is the other way around then exchange the formulae symbols.
let
screenH = screen height in pixels;
screenW = screen width in pixels;
bgW = width of staticbackgroundimage in pixels;
bgH = height of staticbackgroundimage in pixels;
so now, if you want to move 'p' pixels in the background static ludo image horizontally then let us say you will have to move x pixels on the screen. x can be calculated as follows:
x= p*screenW/bgW;
Also, if you want to move 'q' pixels in the background static ludo image vertically then let us say you will have to move y pixels on the screen. y can be calculated as follows:
image height on the screen will be(in pixels):
screenHimage=bgH*screenW/bgW;
y=q*screenHimage/bgH;
So now move x and y pixels on the screen if you want to move p and q pixels in the original image.
I hope this works.

Android - how to pass view coordinates to surface view coordinates

In my app I have scanner view, which must scan two barcodes with zxing library. Top barcode is in PDF417 format, bottom - in DATAMATRIX. I used https://github.com/dm77/barcodescanner as a base, but with main difference: I have to use image coordinates as scan area. Main algorithm:
Depends of current step, scan activity passes current scan area to scanner view in screen coordinates. These coordinates calculated as follows:
public static Rect getScanRectangle(View view) {
int[] l = new int[2];
view.measure(0, 0);
view.getLocationOnScreen(l);
return new Rect(l[0], l[1], l[0] + view.getMeasuredWidth(), l[1] + view.getMeasuredHeight());
}
2.In the scanner view, in onPreviewFrame method, camera preview size is received from camera parameters. When I translated byte data from camera to bitmap image in memory, I saw, that it rotated 90 degrees cw, and camera resolution not equals screen resolution. So, I have to map screen coordinates into camera (or surface view) coordinates:
private Rect normalizeScreenCoordinates(Rect input, int cameraWidth, int cameraHeight) {
if(screenSize == null) {
screenSize = new Point();
Display display = activity.getWindowManager().getDefaultDisplay();
display.getSize(screenSize);
}
int height = screenSize.x;
int width = screenSize.y;
float widthCoef = (float)cameraWidth/width;
float heightCoef = (float)cameraHeight/height;
Rect result = new Rect((int)(input.top * widthCoef), (int)(input.left * heightCoef), (int)(input.bottom * widthCoef), (int)(input.right * heightCoef));
return result;
}
After that, translated coordinates passes into axing and on most test devices all works fine. But not on Nexus 5X. First, there are serious gap between display size and activity.getWindow().getDecorView() sizes. Maybe this is related to status bar size, which is translucent and for some reason it's height maybe not calculated. But, even after I added vertical offset, there are something wrong with scan area. What's may be reason for that error?

Scaling image inside custom view with rotation angle in Android

Well, this might be a bit hard to explain but here is the deal: I have a custom view which has a background image and some other smaller images drawn above it. The whole view, when the user selects the option to save it, will be scaled to a certain resolution, let's say 900x900px. So if the phone is 720p the image will be scaled up, while if the screen is 1080p will be scaled down.
How is scaling done:
I take the view's layout params and change the width to 900px.
The background stored image is exactly at 900px, so when the view is prepared to be saved, I simply reload the background image at full
quality.
All the other small images, get scaled as well, both their size and their position on screen.
So, if initially if the screen size is 720px width, when the size is changed to 900px, I calculate a scale factor, within onMeasure
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
if (MeasureSpec.getSize(widthMeasureSpec) == 900) {
scale = (900 - viewWidth) * 100.2f / viewWidth;
prepareSaving();
}
}
Then I use this scale number when drawing:
canvas.drawBitmap(myCachedImage, x + addScale(x), y + addScale(y), imagePaint);
where
private float addScale(float value) {
if (scale == 0) {
return 0;
} else {
return (value * scale / 100.2f);
}
}
This allows me to draw the bitmap at scaled coordinates, and this works as expected.
The problem appears when the user rotates the image. On rotate I do:
public void rotateSticker(float degrees) {
imageMatrix.setRotate(degrees, imageCenterX + addScale(imageCenterX), imageCenterY +imageCenterY ));
}
Within onDraw I do:
if (angle!=0{
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.setMatrix(imageMatrix);
canvas.drawBitmap(myCachedImage, x + addScale(x), y + addScale(y), imagePaint);
canvas.retore()
}else
{
canvas.drawBitmap(myCachedImage, x + addScale(x), y + addScale(y), imagePaint);
}
Here is my problem: if the user does not rotate, all scaling is done correctly and the saved image looks good. If there is an angle, on scaling, the image is not drawn in the right coordinates, it is moved, just like in the image bellow
http://i.imgur.com/bFBHVF1.png
All the problems with scaling and rotating was caused by the image's Matrix. When I switched to using only the view's canvas.rotate(), everything is working as expected.

Converting Camera Coordinates to Custom View Coordinates

I am trying to make a simple face detection app consisting of a SurfaceView (essentially a camera preview) and a custom View (for drawing purposes) stacked on top. The two views are essentially the same size, stacked on one another in a RelativeLayout. When a person's face is detected, I want to draw a white rectangle on the custom View around their face.
The Camera.Face.rect object returns the face bound coordinates using the coordinate system explained here and the custom View uses the coordinate system described in the answer to this question. Some sort of conversion is needed before I can use it to draw on the canvas.
Therefore, I wrote an additional method ScaleFacetoView() in my custom view class (below) I redraw the custom view every time a face is detected by overriding the OnFaceDetection() method. The result is the white box appears correctly when a face is in the center. The problem I noticed is that it does not correct track my face when it moves to other parts of the screen.
Namely, if I move my face:
Up - the box goes left
Down - the box goes right
Right - the box goes upwards
Left - the box goes down
I seem to have incorrectly mapped the values when scaling the coordinates. Android docs provide this method of converting using a matrix, but it is rather confusing and I have no idea what it is doing. Can anyone provide some code on the correct way of converting Camera.Face coordinates to View coordinates?
Here's the code for my ScaleFacetoView() method.
public void ScaleFacetoView(Face[] data, int width, int height, TextView a){
//Extract data from the face object and accounts for the 1000 value offset
mLeft = data[0].rect.left + 1000;
mRight = data[0].rect.right + 1000;
mTop = data[0].rect.top + 1000;
mBottom = data[0].rect.bottom + 1000;
//Compute the scale factors
float xScaleFactor = 1;
float yScaleFactor = 1;
if (height > width){
xScaleFactor = (float) width/2000.0f;
yScaleFactor = (float) height/2000.0f;
}
else if (height < width){
xScaleFactor = (float) height/2000.0f;
yScaleFactor = (float) width/2000.0f;
}
//Scale the face parameters
mLeft = mLeft * xScaleFactor; //X-coordinate
mRight = mRight * xScaleFactor; //X-coordinate
mTop = mTop * yScaleFactor; //Y-coordinate
mBottom = mBottom * yScaleFactor; //Y-coordinate
}
As mentioned above, I call the custom view like so:
#Override
public void onFaceDetection(Face[] arg0, Camera arg1) {
if(arg0.length == 1){
//Get aspect ratio of the screen
View parent = (View) mRectangleView.getParent();
int width = parent.getWidth();
int height = parent.getHeight();
//Modify xy values in the view object
mRectangleView.ScaleFacetoView(arg0, width, height);
mRectangleView.setInvalidate();
//Toast.makeText( cc ,"Redrew the face.", Toast.LENGTH_SHORT).show();
mRectangleView.setVisibility(View.VISIBLE);
//rest of code
Using the explanation Kenny gave I manage to do the following.
This example works using the front facing camera.
RectF rectF = new RectF(face.rect);
Matrix matrix = new Matrix();
matrix.setScale(1, 1);
matrix.postScale(view.getWidth() / 2000f, view.getHeight() / 2000f);
matrix.postTranslate(view.getWidth() / 2f, view.getHeight() / 2f);
matrix.mapRect(rectF);
The returned Rectangle by the matrix has all the right coordinates to draw into the canvas.
If you are using the back camera I think is just a matter of changing the scale to:
matrix.setScale(-1, 1);
But I haven't tried that.
The Camera.Face class returns the face bound coordinates using the image frame that the phone would save into its internal storage, rather than using the image displayed in the Camera Preview. In my case, the images were saved in a different manner from the camera, resulting in a incorrect mapping. I had to manually account for the discrepancy by taking the coordinates, rotating it counter clockwise 90 degrees and flipping it on the y-axis prior to scaling it to the canvas used for the custom view.
EDIT:
It would also appear that you can't change the way the face bound coordinates are returned by modifying the camera capture orientation using the Camera.Parameters.setRotation(int) method either.

Categories

Resources