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
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.
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.
I am trying to get equal space between my buttons across the screen for any screen size (width). I am using Libgdx tables inside a stage. I think my logic is on the right track but it is not returning anything close to what I want.. most of the buttons are off the screen. (I have 5 buttons total)
int width = Gdx.graphics.getWidth();
int spacing = width / 5;
System.out.println(width);
System.out.println(spacing);
//BOTTOM TABLE
tableBottom = new Table(skin);
stage.addActor(tableBottom);
tableBottom.setBounds(0,0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tableBottom.setFillParent(true);
tableBottom.columnDefaults(1).width(spacing);
tableBottom.add(inventoryButton).size(144,160).center();
tableBottom.add(assignButton).size(148,180).center();
tableBottom.add(shopButton).size(130,152).center();
tableBottom.add(collectButton).size(182,198).center();
tableBottom.add(fightButton).size(162,178).center();
As Requested Images:
This is what the code above is doing! and it is not accurate it does different based on every screen size.
This is what I WANT it to look like. On every Sized screen equal spacing and take up the whole bottom.. obviously a bigger screen they will be not as close together but that is fine! thanks been struggling with this.
To get equal spacing in horizontal direction change
tableBottom.add(inventoryButton).size(144,160).center();
tableBottom.add(assignButton).size(148,180).center();
tableBottom.add(shopButton).size(130,152).center();
tableBottom.add(collectButton).size(182,198).center();
tableBottom.add(fightButton).size(162,178).center();
to
tableBottom.add(inventoryButton).size(144,160).expandX();
tableBottom.add(assignButton).size(148,180).expandX();
tableBottom.add(shopButton).size(130,152).expandX();
tableBottom.add(collectButton).size(182,198).expandX();
tableBottom.add(fightButton).size(162,178).expandX();
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)
Currently I measure the devices DPI, then draw a line at a certain number of pixels based on DPI (if the DPI is 320, then I display a line every 320 pixels).
I have it working on some devices, but then others are way off which has left me very confused...
Any suggestions as to what I am doing wrong?
Heres the code I used to get the devices DPI (among other various things)
metrics = context.getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
xdpi = metrics.xdpi;
ydpi = metrics.ydpi;
densityDpi = metrics.densityDpi;
Then heres how I am drawing the lines across the top of the screen.
x = 0;
while (x <= width) {
canvas.drawLine(x, 0, x, lineHeight, paint);
x = x + xdpi;
}
At first I was using the variable densityDpi to draw the lines, but then I found out thats only an estimated DPI. So I changed the code to xdpi which is supposed to be based on the screens actual pixels however its still not accurate on some devices.
I had the same issue, needed to draw a coin in the exact size it is in real life. Each device should report it's proper DPI, but some (few) devices just provide wrong data. I ended up allowing users to resize the image manually.