I have a picture that I want to animate and move to another ImageView location.
Currently this is what I'm doing :
v.animate()
.scaleX(??)
.scaleY(??)
.x(target.x)
.y(target.y)
.setDuration(1000)
.start()
My question is how can I calculate the correct scale factor for x and y? If I set the layout params equal to the target's layout params, then it works fine but it isn't animated. I've tried dividing the width and height of the source image with the target image, but it hasn't been giving me the correct scale.
Thanks for your help
create a float value for the ratios between the two images:
float w_ratio = (targetImage.getMeasuredWidth() - sourceImage.getMeasuredWidth()) / sourceImage.getMeasuredWidth();
float h_ratio = (targetImage.getMeasuredHeight() - sourceImage.getMeasuredHeight()) / sourceImage.getMeasuredHeight();
// then animate:
v.animate().scaleXBy(w_ratio).scaleYBy(h_ratio).setDuration(1000);
// Don't forget to reset the size later if needed, using:
v.setScaleX(1.0f);
v.setScaleY(1.0f);
A solution will be to get the actual width and height of the images via getMeasuredWidth() and getMeasuredHeight(), and then doing division to compute the scale factor. Note, that using getWidth() and getHeight() is not a good option, as they contain information on width and height (e.g. integer value of MATCH_PARENT), not the final computed value. Also note, that measured with and height is available after UI was laid out. If your animation must be done on activity creation, you must trigger it in onWindowFocusChanged, at this time layout sizes are already computed (if I remember correctly).
imageViewToBeChanged
.animate()
.scaleX(targetImageView.getMeasuredWidth() / imageViewToBeChanged.getMeasuredWidth())
.scaleY(targetImageView.getMeasuredHeight() / imageViewToBeChanged.getMeasuredHeight())
.x(target.x)
.y(target.y)
.setDuration(1000)
.start()
EDIT
Also, I am not sure how much scaling will affect the quality of image inside ImageView.
To get the x and y position of your target imageView write the following code.
x = imageViewObject.getLeft();
y = imageViewObject.getTop();
To animate you need to make the following changes in your code
v.animate()
.scaleX(0) // This will be your initial x position of your imageView
.scaleY(0) // This will be your initial y position of your imageView
.x(x) // This will be the x position of your target imageView
.y(y) // This will be the y position of your target imageView
.setDuration(1500)
.start()
Initially, for testing purposes increase the duration so you can notice the animation and can make necessary changes if required.
Related
Here's some background information. I'm making an Android app that requires an ImageView to be shown on the screen in the same physical size (xInches by yInches) regardless of the device that the image is being shown on. The problem I'm having is that the size of the ImageView, by default, changes size depending on the current screen resolution and the screen size.
What I need is a function that:
Has inputs of the ImageView I need to resize, the x (in inches) of the preferred size, and the y (in inches) of the preferred size
Computes the pixel dimensions of something x by y inches (the magic I need to figure out how to implement)
Returns the calculated x and y dimensions in dpi/px or something that I can easily apply to the ImageView
I'm kind of new to developing for Android, so I'm not 100% familiar with the different coordinate systems, such as px vs dpi, but all I'm looking for is a way to correspond these coordinate systems with physical coordinates.
By the way, I'm only using inches because I live in the U.S. However, what I mean to say is any unit that measures in physical space rather than screen space.
Thanks for your help!
For such a task you will probably need to find the device's dpi and then resize the image based on that. So something like
String inchesToDp(int x, int y){
DisplayMetrics metrics = getResources().getDisplayMetrics();
//int densityDpi = metrics.densityDpi; used for general purpose
int xInch = x * metrics.xdpi; //1 inch in dpi is just the amount of dpi
int yInch = y * metrics.ydpi; //x and ydpi give exact lcd dpi for horizontal and vertical but you could just use x * densityDpi if it doesn't matter
return "x in dp: " + xInch + "y in dp: " + yInch;
}
as i understand your question:
for using an imageview in android first of all you should use a viewgroup like linearlayout or relativelayout an put you imageview inside it. the usual attributes using for imageviews for height & width is match parent. by doing this if your screen changes, your imageview changes in relation to your screen.
My Activity has a Canvas with both width and height equal to 6000. When I start the Activity the upper left coordinate of my screen is (0,0) so screen' center is about (30,60). What I want is start the Activity with coordinates (3000,3000) in the center of screen
any solution?
Update 1:
I used this Kotlin code:
var fondo = Lienzo(this) //fondo is the Canvas View (6000,6000)
val scrollV = ScrollView(this)
val hscrollV = HorizontalScrollView(this)
scrollV.addView(fondo)
hscrollV.addView(scrollV)
layaout1.addView(hscrollV) //layaout1 is a RelativeLayout
More code would be nice since I cannot see where you are declaring the position but if you are hard-coding the coordinates, I would suggest instead of using the same variables for width and height and just putting them in the coordinates /2 so if your variables are width and height, it should be kind of like this depending on what you are using:
.setPosition(width/2, height/2);
If this isn't useful then please provide more info or more code to see where your mistake is :)
That's not how Canvases work in Android. You don't declare how big you want it to be and it magically scales to the screen. If you're in the View's onDraw function, the Canvas passed in is the size of the View, in physical pixels. You need to scale your drawing to it. If you're drawing to an offscreen bitmap first and then blitting that to the screen, its your job to scale the bitmap via a matrix when you blit it. Also, in Android the coordinate system is 0,0 as the upper left hand corner. Unless it greatly eases your drawing I suggest you not fight it.
However you could use a matrix transformation on the Canvas to change that. First you'd want to scale the matrix by 6000/view.getHeight() in the y and 6000/view.getWidth() in the x. Then you'd want to translate it by -3000 in the x and -3000 in the y. That should scale it to the view and move origin to center.
I have animation working with tabsView, when the tabs are changed, the icons of these tabs move to the center with distance of int 54 which is transformed into dp-s shown below, and I have also indicator moving the distance of 70dp the same way, the problem is that animation works perfectly, but the distance is the same for all screen sizes which looks bad for small or too big screens, so is there any way to replace these distances using MATCH_PARENT variable so that result would be same for all screen sizes?
IndicatorTranslationX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,54,getResources().getDisplayMetrics());
endViewsTranslationX = (int) ((mCenterImage.getX() - mStartImage.getX()) - IndicatorTranslationX);
newTranslationX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,70,getResources().getDisplayMetrics());
mIndicator.setTranslationX((positionOffset -1) * newTranslationX);
Use DisplayMetrics to get width and height of the device screen.
See this question
I'm trying to set the height of a view in my application to a fraction of the total height of the user's screen. However, I can never seem to get it to quite work. Other solutions I've looked at for getting the height of the screen in pixels give a good approximate position, but the view position and height seem to vary from screen to screen.
How do I go about this?
Thanks for the help
to get the screen dimensions you can use:
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels;
You will want your view to preserve its aspect ratio, when resizing it, regardless of the screen size.
If you have a view, when it looks ok is 400 px wide and 200 px high, you will want to preserve this ratio (400/200) = 2 after you rescale the layout.
Lets say the screen is 480 w x 800 h and you want your view to be 50% of the width of the screen.
Then 480 * 50% = 240 will be target width of your view.
But we want to preserve aspect ratio:
400/200 = 2 = target width / target heigh = 240 / X
then X = 240*200/400 = 120
Your new Layout for the view should be 240w x 120 h (240 / 120 = 2 -aspect preserved-)
Here, as Android devices have different sizes in terms of aspect ratio (width / height), you may want to check how the new hight fits within the screen hight.
120 / 800 = 15% in this case.
If the hight % doesn't meet what you need, or if the hight happens to be out of bounds of the screen, or if the new hight doesn't meet a minimun height you want, then, you do the inverse calculation by setting a height and calculating the new width allways respecting the aspect ratio.
In this way the view won't deform on any screen.
well i think you might already have tried this trick below.
get width and height in pixels by using displayMetrics.widthPixels and displayMetrics.heightPixels respectively
then (assuming you have relative layout, whose position you want to set) set params as-
RelativeLayout.LayoutParams layoutParam;
set margin as below
//margin (left, top, right, bottom) in pixel CO-Ordinates
layoutParam.setMargins(screenWidth/108+screenWidth*seekTime/29, screenHeight/13, (screenWidth-screenWidth*seekTime/29)+screenWidth/108, (int) (screenHeight/0.9));
here the numbers in denominator (108, 29, 13, 0.9), i got from trial and error method, that suited my project best
so basic idea is to set it at a fraction of screen height in pixel.
for my project it worked for all the devices we tested on an also we had orientation locked to 'portrait'. might not work properly if screen orientation is changed
Another way might be, if you would like go after it...
Make margins a function of screen width.
eg:
if(height>4){
set at half height
}
else{
set at one-third height
}
(and i do hope that you do call display matrix only once in your whole app and store, say at launch of first activity, and just manipulate the margin from the stored place)
I am trying to make a simple app just to understand better how to use Touch events on Android. Right now, my Activity just moves an ImageView to the coordinates of the touch on the screen (the MotionEvent's coordinates). I could manage to do this by applying a simple trick to set the new position of the image to a value that is made of the touch coordinates relative to the position of the image (getX() and getY()). The dx and dy variables are responsible to store this relative values so the touch keeps constant within the image.
Now I want to put 2 ImageViews in the Activity and have only two fixed spots for ImageViews and once the user drags one ImageView over the other ImageView's center, the two images switch places, but to do that correctly I would like to get the real coordinates of the image center. I commented the parts of the code that make it work correctly to show the issue. As you can see in the first picture when the view is created, the Image Coordinates are simply (0, 0), no matter where it is (as long as the initial position is defined as a layout parameter like CENTER_IN_PARENT).
As you can see in the second picture and as far as I observed ImageView's getX() and getY() return the coordinate as if the top-left corner of the image was in the top-left corner of the DISPLAY when the image is located at the top-left corner of the ACTIVITY WINDOW.
I would like to understand why that happens and if anyone knows how to actually get the coordinates of ImageView that can be directly compared to the coordinates of MotionEvent.
Pictures:
FIRST PICTURE
SECOND PICTURE
I still don't know exactly why getX(), getY(), setX(), and setY() do not represent the position of the View on the screen, but I figured out how to get the actual location of the view objects on the screen: getLocationOnScreen(coordinates). Where coordinates is a 2 position int array (int[2]).
For example, to get the real value correspondent to the top-left corner of my ImageView image I simply need to do something like:
int[] img_coordinates = new int[2];
ImageView image = (ImageView) findViewById(R.id.myImage);
image.getLocationOnScreen(img_coordinates);
And then I can actually compare these coordinates with the Touch-event's getRawX and getRawY.
If I want to get the center point of my view I just need to do this:
x_center = (double)img_coordinates[0] + image.getWidth()/2.0;
y_center = (double)img_coordinates[1] + image.getHeight()/2.0;
I hope this helps other people too, it took me a while to find this approach and I am actually not sure if it is the best approach but it does the trick for me.