I know this question has been answered many times but those answers are not helping me out. My app is looking perfect on 5inch screen but on 6 inch and more the alignment is different. I have added tag in manifest also...and also designed layout,layout-large,layout-normal also.
I want to know what is the best way to make the layout supports all screen without making 3 or 4 layouts for one screen.
To support multiple resolutions, you may use multiple layout files, but using a single layout file makes file maintenance and management easier. When you need to modify part of the layout for different resolutions, it is good to use dimens.xml, which makes it easy to modify.
This link may help you:
http://developer.samsung.com/technical-doc/view.do;jsessionid=4D620DFCC329BEC0DB60E73C6B185743?v=T000000126
sorry for answering instead of commenting but that is because of my low reputation, you can find this article helpful for you for the developers of google
https://developer.android.com/guide/practices/screens_support.html, Also this video
https://www.youtube.com/watch?v=GTd7QVv7lzg
There are different ways to approach your problem.
1. You can create different XML s for a same layout based on the screen sizes like normal, 7 inch and ,for large screens (i don't recommend this though )
A set of six generalized densities:
ldpi (low) ~120dpi
enter code here
mdpi (medium) ~160dpi
hdpi (high) ~240dpi
xhdpi (extra-high) ~320dpi
xxhdpi (extra-extra-high) ~480dpi
xxxhdpi (extra-extra-extra-high) ~640dpi
read here(how to create multiple XMLS) --> https://developer.android.com/guide/practices/screens_support.html
2.Give sizes based on a ratio
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenHeight = size.y;
screenWidth = size.x;
now you have values for the screenHeight and screenWidth of that particular devise
now position layouts
eg: how to position a view as linear
topLinearLayout = (LinearLayout) inflateView.findViewById(R.id.top_len_one);
topLinearLayout.setGravity(LinearLayout.HORIZONTAL);
topLinearLayout.getLayoutParams().width = width;
topLinearLayout.getLayoutParams().height = 495 * height / 1920;
eg: how to position a view as relative
RelativeLayout.LayoutParams relativeLayoutForPassword = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
relativeLayoutForPassword.setMargins(screenWidth * 240 / 1080, screenHeight * 960 / 1920, 20, 0);
editTextPassword.setLayoutParams(relativeLayoutForPassword);
// 1080 is my default wire frame's design width , 1920 is height (in pix)
so its like ,
i have an image which is 1920 in height and 1820 in width
create a layout which has 210 height in my default wire frame's design height and set resize it to my devise screen size --> 210/1920 * your devise height
this keeps the perfect ratio for any screen
Related
I'm struggling with a pretty trivial task in the Android "multiple-screen sizes" domain.
What I'm trying to achieve
A layout matching the screen width, with a nine-patch background which resizes (only horizontally, since there is always enough vertical space). Here is a dummy image:
My goal is, depending on the screen resolution, to display the image at the highest resolution possible, by using a set of different sizes, eg. 320x45, 480x67, 600x87, 720x101, without any down-scaling. I'm hoping for a non-programmatic solution.
An example with the above mentioned image sizes would be:
3.7" Nexus One (480 x 800) - the 480x67 image would look best.
4.7" Galaxy Nexus (720 x 1280) - the 720x101 image.
4.7" Nexus 4 (768 x 1280) - again the 720x101 image, stretching to the full 768 px width and becoming 768x101.
Issue
The whole Android resource allocation revolves around dps (density-independent pixels), when in fact I want to display an image based on the actual available pixels.
If I allocate the 480x67 image to res/drawable-mdpi and a 600x87 to res/drawable-hdpi, then image would display correctly on a 5.4" display of 480x800, i.e. mdpi display. However, a 4" 480x800 displays qualifies as hdpi and the system would appoint the 600x87 image, which won't fit the screen.
I tried the smallestWidth parameter as described in the online guide, but that yields strange results. For instance, a 3.7" 480 x 800 display (hdpi) uses my drawable-sw320dp image, although there is a drawable-sw480dp resource available too.
What is the best way to assign a stretchable, width-matching image with the best possible quality? Isn't there any non-programmatic solution?
Thanks in advance!
I believe that by combining density and screen size resource qualifiers you can achieve a close to optimal behavior.
Lets assume this kind of resource folders structure:
drawable-normal-hdpi - A normal size dictates minimum width of
320dp. hdpi dictates 1.5X dp to pixel multiplier. So the minimum px
width of the normal hdpi bucket is 480px. We put here a 480px wide
image.
drawable-normal-xhdpi - Again size dictates 320dp but this time
with 2X multiplier. So we use a 640px wide image.
drawable-xlarge-mdpi - Size means at least 720dp. mdpi multiplier
is 1X, so we use a 720px wide image.
Now lets look at some devices to see how they fall in with those buckets:
Nexus one - normal hdpi. Actual px width: 480px. The image fits
perfectly.
Galaxy nexus - normal xhdpi. We could fit a 720px image, so the
640px image we use isn't optimal - but it's very close.
Nexus 4 is just like the Gnex.
Nexus 10.1 (1280X800) - xlarge mdpi. We could fit 800px, our image
is 720px. Again not ideal but close enough.
Worst case scenario: image used could have 5-10% better quality.
Best case: perfect fit.
The main down side of this method is that you need to provide a lot of resources and folders to account for all the permutations of sizes and densities (even worse if you need to combine that with more qualifiers for locale, orientation and so on). However, as far as my Android understanding goes I don't think you can achieve something better than this without coding.
A remark regarding smallestWidth: Your example for the weird behavior is actually the expected behavior.
hdpi multiplier is 1.5 - So a 480px wide hdpi display is exactly 320dp wide. This makes the drawable-sw320dp the right choice, as documented. I'm not sure if you can combine the smallestWidth qualifier with the dpi qualifier. If it's possible you might get more accurate results than just size modifiers. But this would mean a lot more permutations for a 5% increase in image quality. Probably not worth it.
Actually, your method is not how it is supposed to be. I will suggest 2 ways for you, one is easy but doing programmatically, other one is using a custom view.
Method 1 - Programmatically
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int screenWidth = displaymetrics.widthPixels;
// this will determine "scale ratio" so using which image height and width won't matter
int imageOriginalHeight = 101; // your original image height
int imageOriginalWidth = 720; // your original image width
int imageScaleHeight = (screenWidth*imageOriginalHeight) / imageOriginalWidth;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(screenWidth, imageScaleHeight);
imageView.setLayoutParams(params);
imageView.setImageResource(R.drawable.file);
Method 2 - Custom View
You can use a custom view called ScaleImageView which is written by Maurycy Wojtowicz.
Class is defined like below:
This view will auto determine the width or height by determining if
the height or width is set(exact size or match_parent) and scale the
other dimension depending on the images dimension This view also
contains an ImageChangeListener which calls changed(boolean isEmpty)
once a change has been made to the ImageView
Here is how you are going to implement it.
Create a class named ScaleImageView.java and copy contents of the link above.
In your xml file, create a ScaleImageView, just same like ImageView (the example I am writing below is for filling screenwidth, and scaling height according to that so there will be no empty spaces on right/left)
<com.project.customview.ScaleImageView
android:id="#+id/scaleImageView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
android:src="#drawable/file" />
If you need to declare and set programmatically in your Activity, it is also the same as using ImageView:
imageView = (ScaleImageView)findViewById(R.id.scaleImageView);
imageView.setImageResource(R.drawable.file);
In android you have the option hdpi, mdpi, xdpi,etc..
folders for that , you have to create different images according your device resolution and put your images at there after confirming your device resolution and density category.
for the more reference why it'll happen you can see here
here i explain some chart may be helpful to you.
Low density Small screens QVGA 240x320 (120dpi):
drawable-small-ldpi (240x320)
drawable-small-land-ldpi (320x240)
Low density Normal screens WVGA400 240x400 (x432) (120dpi):
drawable-ldpi (240 x 400 )
drawable-land-ldpi (400 x 240 )
Medium density Normal screens HVGA 320x480 (160dpi):
drawable-mdpi (320 x 480 )
drawable-land-mdpi (480 x 320 )
Medium density Large screens HVGA 320x480 (160dpi):
drawable-large-mdpi (320 x 480 )
drawable-large-land-mdpi (480 x 320)
Galaxy Tab ( 240 dpi ):
drawable-large (600 x 1024)
drawable-large-land (1024 x 600)
High density Normal screens WVGA800 480x800 (x854) (240 dpi):
drawable-hdpi (480 x 800)
drawable-land-hdpi (800 x 480)
Xoom (medium density large but 1280x800 res) (160 dpi):
drawable-xlarge (800 x 1280)
drawable-xlarge-land (1280 x 800)
I am using image say 85x85 px (putting this image in drawable-mdpi)
and if i am displaying this image of 85x85 px on [320x480]mdpi screen size device it looks good,
but while displaying this image on [480x800]mdpi device it looks very small.
I wants to know how can i resize this image of (85x85 px) so that it works fine for the device having screen width and height of 480x800, mdpi.
You have to set the image size in the xml in dp. This post is really helpful.
Consider MDPI image(let say 85x85) as baseline Create images as follow
FOLDER ImageSize Percentage
LDPI 64x64 75% of baseline
MDPI 85x85 100% BASELINE
HDPI 127x127 150% of baseline
XHDPI 170x170 200% of baseline
The better solution for this is to produce LDPI,MDPI,HDPI,XHDPI,XXHDPI sized images and place it inside the corresponding folders.
Put the image in /drawable, and define the size of the image in your XML as 85dp, it will then be scaled for LDPI/HDPI/XHDPI/XXHDPI and god forbid XXXHDPI.
However, the better solution would to produce HDPI(128px)/XHDPI(170px)/XXHDPI(255px) version of the graphics and put them in /drawable-hdpi, /drawable-xhdpi, /drawable-xxhdpi respectively. This way you can provide the best experience for your users.
[Edit]
"dp" is Android's way of defining physical size of an UI objects, so a button of 48x48dp will have roughly the same physical dimension even when run on screen sizes between 240x320 to 1080x1920, for more information check Android developer site's Supporting Multiple Screens.
[Edit 2]
For images on canvas you can use this to calculate the scaled size of the image:
DisplayMetrics dm = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(dm);
int newSize = (int)(85 * (dm.densityDpi / 160f));
How can I put different resources for different dpi on ICS with the same sw800dp smallest width?
Details: There are two tablets with ICS 4.0.4. First one has 1280x800 resolution and mdpi (160) density. Second one has 1920x1200 resolution and hdpi (240) density. So in terms of smallest width they both have the same sw800dp qualifier but different mdpi/hdpi density qualifiers.
I need to have different layouts and images for these two resolutions.
So I created two directories:
layout-sw800dp-mdpi
layout-sw800dp-hdpi
I thought that each device will choose its own directory according to the smallest width AND density.
BUT both of them take resources from the same sw800dp-hdpi folder!
I'm very confused and do not know how to separate resources for that two different resolutions.
Any help is really appreciated.
Thanks in advance.
You should use the same layout, located in /layout/sw800dp, and create /drawable-mdpi , /drawable-hdpi to put your custom drawables, the system will apply the correct ones to each device, using the same layout. Those devices should have similar size and aspect...
Use this to get the density:
float density = getBaseContext().getResources().getDisplayMetrics().density;
Screen height:
int h = 0;
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
h = (int) display.getHeight();
Screen width:
int w = 0;
Display display = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
w = (int) display.getWidth()
After that just select the correct resources.
I have created the activity with a button. I need to specify the height and width of the button like below.
Button btn=new Button(this);
btn.setWidth(100);
btn.setHeight(100);
For multiple screen support is it a right way to specify the size of the view . Guide me to set the height and width to the view.
It really depends on how you want to determine the button size. Basically you have two options
Constants like FILL_PARENT or WRAP_CONTENT
A number
If you choose the 2nd way, you must also choose a strategy, eg
30% of the screen/parent width (so it shrinks/grows depending on the screen actual size)
1 inch on all screens
The former is trivial: just get the width of the target element (either via DisplayMetrics if it's the whole display, or with getWidth() if it's a View) and multiply it by your coefficient.
The latter requires you to know the density of the display, ie how big is a pixel on the device. For example by doubling the density, the pixel width will halve
DENSITY PIXEL SIZE
100 dpi 1/100 in
200 dpi 1/200 in
So if you want your button to be 1 inch wide on all possible devices, you can use
button.setWidth(1 * (int) metrics.xdpi); //1 inch * DisplayMetrics.xdpi
There is a little variant if you know the size in pixels on a MDPI device, ie a device where one DIP is one pixel on an approximately 160 dpi screen. In this case you can use the following
button.setWidth(100 * metrics.density);
This is the javadoc for DisplayMetrics.density:
The logical density of the display. This is a scaling factor for the
Density Independent Pixel unit, where one DIP is one pixel on an
approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
providing the baseline of the system's display. Thus on a 160dpi
screen this density value will be 1; on a 120 dpi screen it would be
.75; etc. This value does not exactly follow the real screen size (as
given by xdpi and ydpi, but rather is used to scale the size of the
overall UI in steps based on gross changes in the display dpi. For
example, a 240x320 screen will have a density of 1 even if its width
is 1.8", 1.3", etc. However, if the screen resolution is increased to
320x480 but the screen size remained 1.5"x2" then the density would be
increased (probably to 1.5).
#Karthick If your button is not used in xml of android layout then you can do below thing for set Button width and Height.
Use Below code to get known what is device height and width.
int public static int LDPI_BUTTONSIZE=100;
int device_height;
int device_width;
WindowManager wm=getWindowManager();;
DisplayMetrics dm=new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
device_width=dm.widthPixels;
device_height=dm.heightPixels;
From Above Code you will decide in which screen of your android device ,for Example you can refer this link of developer click here. in that Refer Table No 3.
Now if your device is LDPI then you can set Button value like this.
Button btn=new Button(this);
btn.setWidth(LDPI_BUTTONSIZE);
btn.setHeight(LDPI_BUTTONSIZE);
For this purpose you need to convert pixels to dp's. You can do this with TypedValue.
Example:
int buttonWidthInPixels = 100;
float buttonWIdthInDp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
buttonWidthInPixels, getResources().getDisplayMetrics());
button.setWidth((int) buttonWidthInDp);
If instead you want to convert to SP (for text), use TypedValue.COMPLEX_UNIT_SP as the first parameter for applyDimension(). See this page on the Android dev guide.
In one of the application I need to make sure that UI components will be placed at proper position in all the screen resolution devices. I have gone through the support multiple screen resolutions tutorial on android developer site. Based on that it seems I may have to create separate layout files for small, normal and large screen devices. Now, the issue in this is that even in large screens there are different resolutions such as 480 * 800 and 480 * 854. In the screen the components gets misplaced slightly. I have set top margin as 100 dip then for 480 * 800 it appears properly but for 480 * 854 it is misplaced slightly.
Can someone let me know how to handle this now?
both the resolutions are considered under the layout-long, so you have to set the layout as per the device's height and width manually.
As per my view this is the best solution . I applied the same solution for my application .
Example
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
height = dm.heightPixels;
width = dm.widthPixels;
if (height == 854 || width == 480)
{
// Your view
}
else
{
// Your VIew
}
You have to check the above condition in onCreate() method of acivity..
It should be possible to differ between WVGA854 and WVGA800 by using:
res/drawable-hdpi-long/
res/drawable-hdpi-notlong/
but i would definately recommend you to design the layouts so that it is robust enough to use one set of layouts for those two screens. It will be too much work to maintain/test of you can't design one layout in that case.