I'm trying to create the control, that allows moving view with the finger. To do this, I follow recommendations from this post.
But presented method needs some modification, to prevent my view from being moved beyond the screen. I found out how to get maxY and maxY coordinates - for my Samsung Galaxy A6 it's 1080x1920. But the problem is, that my maxY is deep beyond the visible bottom edge of the device.
So my control almost disappears, when reaches Y about 1650. What 300 more pixels go for. I can suppose, that this is NavigationBar height + my control view height, but this also doesn't place my control as expected.
I define max coordinates with this method.
private void setMaxCoordinates(int viewWidth, int viewHeight) {
Display display = getWindowManager().getDefaultDisplay();
Point displaySize = new Point();
display.getSize(displaySize);
maxX = displaySize.x - viewWidth;
maxY = displaySize.y - viewHeight;
}
Please, help me to define the correct formula to detect bottom edge coordinate.
I've found a solution. First of all I was wrong with getting bottom coordinates with the help of WindowManager. This just gives you height of your screen in pixels, that is not related to the container. So to detect your bottom coordinate this way, you have to consider:
StatusBar height.
NavigationBar height.
Height of all views that lokated higher, then your container.
Height of your own control view (ImageView in my case).
So formula will look like this.
maxY = windowHeight - (statusBarHeight + navBarheight + allUpperViewsHeight + yourViewHeight)
The correct way to define the bootom of your container, is to get the container's height and deduct your control height.
maxY = containerHeight - yourViewHeight;
Related
Inside a FrameLayout, I have a view which absolute coordinates I get thanks to a MotionEvent (getRawX() and getRawY()). However when I apply those same coordinates to that same object (with LayoutParams), the object appears moved (Both X is increased by a little bit because the padding on the sides is very small, Y is increased by a lot because there is a lot of space above the containing object).
I have tried applying the parameters and then substracting the getTop() from the view, but it still gives appears moved. I have also tried substracting the height of the actionbar but it still is quite a few pixels off.
Is there any way to apply those RawX and RawY inside a containing View with precision?
The problem was that even though I substracted getTop() and the action bar height, I didn't substract the bottom padding of the view.
So basically you need to substract the space above the container view, the action bar height AND the space below it (aka the root view's padding) to make up for the fact that the MotionEvent gives you only absolute coordinates.
Retrieving the action barheight:
int actionBarHeight;
if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
{
actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
}
Getting the coords:
params.topMargin = (int) me.getRawY() - (view.getHeight() / 2) - (draggedMobsArea.getTop() + actionBarHeight) - rootLayout.getPaddingBottom();
params.leftMargin = (int) me.getRawX() - (view.getWidth() / 2) - draggedMobsArea.getLeft();
view.setLayoutParams(params);
I have the next question:
Im developing an app that when i move a imageView and drop it, if the view drops under the half height of the screen goes to a (X,Y) position and if is over the half height screen, goes to another position.
I need to calculate the half of the screen generic, so i use the next code:
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
halfHeight = displaymetrics.heightPixels / 2;
This works great, im trying in a screen 1920x1080, the code returns 540.
But when im going to see if when i drop the view is under or over the half, here is what i dont understand. i get the Y position of the view and is ok, what i dont understand is why the Y = 0 is not on the TOP of the screen, if i move the view to the top, i get a negative Y position like -260.
Someone can explain me why this happen?
Is there i way that the (0,0) position starts in the top left of the screen?
Greets, hope you understand
If you call getX() or getY() then you are getting relative values for x and y (relative to the view that the call was dispatched from). If you call getRawX() or getRawY() it will give you the absolute position of the view relative to the device's screen.
Most likely you are getting negative values of -260 because you are dragging the ImageView 260 away from the view in which the call was made (perhaps the view on the top of the screen has a height of 260). If you are trying to use getX() or getY() to calculate the middle of the screen then you would have to take all sizes of all views into consideration but I think you want to use getRawX() and getRawY()
An angle of 0 degrees correspond to the geometric angle of 0 degrees (3 o'clock on a watch.)
try using translate to translate the co-ordinates to top of the screen.
http://developer.android.com/reference/android/graphics/Canvas.html#translate(float, float)
To get view right edge after rotating it around Y-axis with fixed pivot point I'm using the below code and that is working like it should.
view.setPivotX(0);
view.setPivotY(view.getHeight() / 2);
view.animate().rotationY(rotationAngle).start();
view.getMatrix().mapRect(rectF);
int rightEdge = rectF.right;
Now what I want to do next is to calculate rotationAngle so the right edge of the view will be a specified value (let say 1000px). Any idea how to reach this ?
I am working on a very simple Physics game for Android where an object bounces up and down with some gravity (0 friction, ball should always reach same height). I want it to reach the same height on all devices (density independence). My game is coded with the following for the physics, which works perfectly fine on a 540 * 960 device.
Note: My game has a max FPS of 30
physics code
//Instance variables
private final float acceleration = .1f;
private static float timePoint;
private float velocityY = 0;
//game loop code
timePoint += 1;//updates every tick
velocityY = velocityY - acceleration * timePoint;
position.y = (int) (position.y - velocityY);
if(position.y + bitMapHeight <= 0){
velocityY = 30;
timePoint = 0;
}
When the ball hits the ground (y = 0) I simply apply a velocity of 30, which makes the ball reach a desired height on the 540 * 960 device. Of course multiple devices lead to major headaches, and this formula will not suite all of them. I think the best approach would be to somehow calculate the velocity based on screen height, but I'm not really sure what the best approach is for something like this. Below are some screenshots showing whats happening.
If anyone can point me in the right direction I would be very grateful! Please let me know if any more details are required.
I had to solve a similar problem in a 2D game I was working on a while ago.
I developed the initial physics and rendering functionality on my own Android device until it behaved nicely on that particular device. I then obtained 'baseline' values for the relevant variables (eg. pixels:meter as mentioned by bjb568), to achieve the correct velocities on my baseline device.
Then, to make the game behave in the same way on different devices/screens, I simply used the baseline values scaled by the ratio of the actual screen resolution and the baseline screen resolution.
My game used a SurfaceView, so the 'actual screen resolution' was basically determined by the width and height of the surface.
I hope that helps.
Why don't you try this on the onCreate:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
With that you can get the values of the screen and, instead of using ´velocityY = 30;´ you can set it to ´velocityY= height/10´ for example
Why you set velocityY = 30; after point reaches the bottom? I think that you should use perfectly elastic collision. So, you just need to set velocityY = -velocityY;
I apologize to those who posted on this for my delayed response. I found a solution that worked for me. Below is the approach I took.
Find the target height that the object should reach after it hits the ground (bottom of screen).
//We want the object to bounce halfway on screen
targetBounceHeight = metrics.heightPixels / 2;
Use physics calculation to find required velocity to reach point Y.
double velocityI = Math.sqrt(2 * targetBounceHeight * acceleration);
I simply find the initial velocity required, then plug it into the original code snippet dynamically instead of the value 30 (see top post). This solution has worked on all tested devices perfectly. Hope this helps someone!
I have an image view which is contained within a relative layout. I am trying to get the screen y coordinates of the top of the image view and the screen y coordinates of the bottom of the image view. I have tried this:
float yMin = (float)levelH.getTop();
float yMax = (float)levelH.getBottom();
float yMin seems almost correct. I am translating another image view (IM2) up and down this image view(IM1). So I am trying to set a limit on how far (IM2) can translate up and down. So my thinking was to get the y top and bottom of (IM1) I can set those as max and min.
Anyone know how to do this?
ps Im using android accelometer to move (IM2)
getTop() ansd getBottom() look at coordinates within it's parent. To get coordinates of it's position on the screen you can use getLocationOnScreen
Use it like this:
int[] coords = {0,0};
view.getLocationOnScreen(coords);
int absoluteTop = coords[1];
int absoluteBottom = coords[1] + view.getHeight();
Use View.getLocationOnScreen() and/or getLocationInWindow()