I want to make folders of dimens according to screen size and not according to density so what will be the dp values for each screen size. I want to adjust my DP value according to screen size only and not according to density so is there any formula for calculating dp for different screen size . As there is a relation between density , pixel and dp . But i want it for different screen size . It is like for normal-xhdpi screen and for normal-xxhdpi screen the size of the button should be same as independent of density as name suggest of "DP"
Create three different Layouts Folder in your res folder for all devices and use the dimensions accordingly.
Generic Layout Folders
res/layout-small
res/layout-normal
res/layout-large
res/layout-xlarge
After you are done with making your Normal/Medium Layouts follow these steps:
Convert the Normal Dimensions for other Screen Sizes.
Copy your Normal Layout xml files in to other Folders.
Change the suffix of the dimensions used according to the folder that you are in
Resize the Image Resources in your drawable folder (Width and Height - Same technique as we used for converting the dimens) and put them in their respective drawable folder (drawable-ldpi, drawable-mdpi, drawable-hdpi, drawable-xdpi and so on).
Then your Layouts should work on every device with correct positioning.
For converting Values
0.75 - ldpi (small) //mdpi dimens *0.75
1.0 - mdpi (normal) //First create these dimensions
1.5 - hdpi (large) //mdpi dimens *1.5
2.0 - xhdpi (xLarge) //mdpi dimens *2.0
For Example
android:layout_width="66dip" //in normal
android:layout_width="100dip"//in large 66*1.5=100(approx)
android:layout_width="52dip" //in small 66*0.75=52(approx)
Also new Qualifier has been introduced
- SmallestWidth
- AvailableScreenWidth
- AvailableScreenHeight
read more about it here https://developer.android.com/guide/practices/screens_support.html
If you are looking in Java code
/// convert dp to pixels
public static int dp2px(Context context, float dp) {
return Math.round(dp * context.getResources().getDisplayMetrics().density);
}
I hope this helps.
public static float dpToPx(Resources rs,float dp){
DisplayMetrics metrics = rs.getDisplayMetrics();
float px = dp * (metrics.densityDpi/160f);
return px;
}
public static float pxToDp(Resources rs,float px){
DisplayMetrics metrics = rs.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
Related
I have an ImageView with these attributes:
android:layout_width="match_parent"
android:layout_height="160dp"
UI developer asks me for the size of Image that I want in px. What size should I ask? Should I ask different size for different devices?
Note
I don't have an ImageView with specific height and width. My ImageView width is match_parent not a specific width.
All the answers say that I should use a converter, How can I convert match_parent to px?
According to answers, I should ask about six images, shouldn't I?
You should give highest screen density in pixels to your UI developer then scale to lower densities on your own.
Normally an android app will support screen densities ldpi at min and xxxhdpi at max.
Step1: If you want the image size is 160 x 160 dp then give the UI developer the highest image size associated with max screen density.
160 x 4 = 640x640 px (why multiply by 4? I will explain later)
Step 2: Scale the image 640x640 px to lower size based on screen densities
ldpi: 160 x 0.75 = 120x120 px
mdpi: 160 x 1 = 160x160 px
hdpi: 160 x 1.5 = 240x240 px
xhdpi: 160 x 2 = 320x320 px
xxhdpi: 160 x 3 = 480x480 px
xxxhdpi: 160 x 4 = 640x640 px
Tips: Find your image size corresponds with mdpi density screen (known as base density or 1X density) then scale to other densities by the following formula
Update: From https://material.io/tools/devices/, screen size for base density screen is 360x640 px. So your ImageView size will be 360x160 px on 1X density screen.
ldpi: 270x120 px
mdpi: 360x160 px
hdpi: 540x240 px
xhdpi: 720x320 px
xxhdpi: 1280x480 px
xxxhdpi: 1440x640 px
Why are you not using Vector drawable?
Why use Vectors?
Data can be represented in original resolution without generalization.
Graphical outputs of the images are more pleasing than the created as raster image
Another very important reason of using vector graphics rather than raster is their size. Vector objects are much smaller than raster image format. If we have the full-size image to update, the vector file might only take few kilobytes of space on your system, where the same image in medium resolution bitmap format might not place on CD ROM.
You should use SVG images in your project.
Create SVG instead of PNG files
Ok, you want to set image height of size 160dp (since it is in dp, this is the size in mdpi). So you to have to ask UI developer to make you image of height 4 times of that. Image Height = 4 * 160. After that you can use Batch drawable importer from android studio, to make image for all differrent resolutions. Hope it helps.
Different Devices has Different sizes
android:adjustViewBounds="true" is automaticaly pickup height of image
so you can this,
<ImageView
android:id="#+id/ivImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
You should go with 1440x640 for largest size.
If you want to support multiple devices with multiple images you can have 5 standard image slicings.
mdpi : 360x160
hdpi : 540x240
xhdpi : 720x320
xxhdpi : 1080x480
xxxhdpi : 1440x640
I came up with these image sizes, because if you look at most common display sizes, largest of them is 1440x2960 of Samsung Galaxy S8. (I am aware of 2160x3840, but it is not main stream and I would even say its outright crazy).
In your case you have width set to match_parent which in every case of largest (or even custom) DPI, will be 1440px at most, so you can be damn sure that 99% of the time it will not exceed it. (Most current devices with 9:18 or 9:X ratio devices also feature 1440 px width in almost every case if they go more than 1080. Check out resolutions of latest devices released.)
So you can settle at 1440 px of width. Now height of your ImageView is 160dp. Which can be (as suggested by everyone else) 160*4 = 640 px for largest default DPI xxxhdpi. The reason that you should consider height for standard dpis because it is fixed to some dp (160dp) and this may change for custom dpi devices, so you can support maximum devices with this, 640px size. Hope I was clear about size suggestion.
To provide good graphical qualities on devices with different pixel densities, you should provide multiple versions of each bitmap in your app - one for each density bucket, at a corresponding resolution. Otherwise, Android must scale your bitmap so it occupies the same visible space on each screen, resulting in scaling artifacts such as blurring.
Figure 1. Relative sizes for bitmaps at different density sizes
There are several density buckets available for use in your apps. Table 1 describes the different configuration qualifiers available and what screen types they apply to.
Table 1. Configuration qualifiers for different pixel densities.
To create alternative bitmap drawables for different densities, you should follow the 3:4:6:8:12:16 scaling ratio between the six primary densities. For example, if you have a bitmap drawable that's 48x48 pixels for medium-density screens, all the different sizes should be:
36x36 pixels (0.75x) for low-density (ldpi)
48x48 pixels (1.0x baseline) for medium-density (mdpi)
72x72 pixels (1.5x) for high-density (hdpi)
96x96 pixels (2.0x) for extra-high-density (xhdpi)
144x144 pixels (3.0x) for extra-extra-high-density (xxhdpi)
192x192 pixels (4.0x) for extra-extra-extra-high-density (xxxhdpi)
Then, place the generated image files in the appropriate subdirectory under res/ and the system will pick the correct one automatically based on the pixel density of the device your app is running on:
res/
drawable-xxxhdpi/
awesome-image.png
drawable-xxhdpi/
awesome-image.png
drawable-xhdpi/
awesome-image.png
drawable-hdpi/
awesome-image.png
drawable-mdpi/
awesome-image.png
Then, any time you reference #drawable/awesomeimage, the system selects the appropriate bitmap based on the screen's dpi. If you don't provide a density-specific resource for that density, the system picks the next best match and scales it to fit the screen.
Tip: If you have some drawable resources that the system should never scale (perhaps because you perform some adjustments to the image yourself at runtime), you should place them in a directory with the nodpi configuration qualifier. Resources with this qualifier are considered density-agnostic and the system will not scale them.
Official Source: Screen Densities
This is an official size chart given by Material Design Or you can ask for xxxhpdi which is 1440 x 2960 px based image and use this site to get all the images with various densities.
When you get images with various densities, no need to specify height and width in px layout. Keep the images with same name and use match_parent. Android will automatically choose the image according to the device.
try this source code
Display display = getWindowManager().getDefaultDisplay();
String displayName = display.getName(); // minSdkVersion=17+
Log.i(TAG, "Pantalla = " + displayName);
// Tamaño en píxeles
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Log.i(TAG, "Ancho = " + width);
Log.i(TAG, "Alto = " + height);
// dpi
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int heightPixels = metrics.heightPixels;
int widthPixels = metrics.widthPixels;
int densityDpi = metrics.densityDpi;
float xdpi = metrics.xdpi;
float ydpi = metrics.ydpi;
Log.i(TAG, "Ancho en píxeles = " + widthPixels);
Log.i(TAG, "Alto en píxeles = " + heightPixels);
Log.i(TAG, "Densidad dpi = " + densityDpi);
Log.i(TAG, "x dpi = " + xdpi);
Log.i(TAG, "y dpi = " + ydpi);
// Deprecated
int screenHeight = display.getHeight();
int screenWidth = display.getWidth();
Log.i(TAG, "Alto de pantalla = " + screenHeight);
Log.i(TAG, "Ancho de pantalla = " + screenWidth);
// Orientación
int orientation = getResources().getConfiguration().orientation;
Log.i(TAG, "Orientación = " + orientation);
Yes you would need to take multiple images for different screen sizes, if you do not want to use vectors and wish to use images (png,etc.) instead.
Since you have width as match_parent, in this case take the images with the max screen width for different density buckets:-
MDPI -> 320 px
HDPI -> 480 px
XHDPI -> 640 px
XXHDPI -> 1080 px
One dp is a virtual pixel unit that's roughly equal to one pixel on a medium-density screen (160dpi; the "baseline" density).
According to the above statement , you the find the heigth for the images :-
MDPI -> 160 px
HDPI -> 240 px
XHDPI -> 320 px
XXHDPI -> 480 px
How to calculate :-
Consider, 160 dp would be 160 px in mdpi(1x).
160 dp would be 240 px in hdpi (1.5x).
and so on..
OR using the function px = dp * (dpi / 160)
For HDPI , dpi is 240
px = 160 * 240/160
px = 240
For dpi list refer this
This helped me to figure it out, and make things clear
You can refer this
ldpi: 270x120 px
mdpi: 360x160 px
hdpi: 540x240 px
xhdpi: 720x320 px
xxhdpi: 1280x480 px
xxxhdpi: 1440x640 px
I am new to the concepts of android layouts associated with different screen sizes. I wish to make a different layout for a tab which is of 8" and place it in a "layout-swxxxx" folder. And have another generic layout for tabs bigger than than 8" in "layout" folder.
Here is the configuration of my 8" tablet.
Screen size 8.0 inches
Resolution 1200 x 1920 pixels (~283 ppi pixel density)
Can anyone tell me how to calculate the "sw", so that i can name my layout folder accordingly.
Also I don't have the physical device with me so its not possible for me to find this value with any code. So request an alternative method.
Thank you in advance.
The formula linking dp, pixels and density is as follow :
px = dp * (dpi / 160)
Therefore, in your case,
widthInDp = widthInPx / (dpi / 160)
widthInDp = 1200 / (283 / 160)
widthInDp = ~678dp
So you're gonna want to use a bucket such as sw600dp
Reference : http://developer.android.com/guide/practices/screens_support.html
if a Custom View of size 500w*600h in dp , remain same as px in (1152w*720h)px screens of android , then what will be view's size in dp and px on screen of (480w*600h)px screens. And how to calculate for different size of View.
The dp / px ratio is based on the density of the screen of the device.
I would encourage you to read the Android docs on the subject.
http://developer.android.com/guide/practices/screens_support.html
Each classification of screen density has a specific px multiplier associated with it i.e. mdpi = px * 1 and hdpi = px * 1.5
Here is a nice little calculator to help you make sense of it:
http://labs.rampinteractive.co.uk/android_dp_px_calculator/
Assuming that you specified your view sizes in dp(same as dip), you can use get an instance of DisplayMetrics to convert the dp to actual pixels for your current device.
A handy function you can add to a utility class for doing conversions:
private static float dipToPixels(Context context, int dip)
{
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, metrics);
}
In android applications, we maintain dimen.xml for various screen resolutions. Say for example I am using device X as base development device and defining dimen.xml relative to device X. Now if I want to know what will be corresponding dimen.xml for a different density device what procedure/strategy can be followed here?
For example:
If I define margin_10 as 10dp in dimen.xml. what value margin_10 will have for different dimen.xml depending on density type (hdpi, xhdpi, xxhdpi, xxxhdpi)?
Thanks
Since you are defining the size in dp units, you need not worry about giving multiple sizes for other resolutions.
From the developer docs:
A dp is a density-independent pixel that corresponds to the physical size of a pixel at 160 dpi.
The density-independent pixel is equivalent to one physical pixel on a 160 dpi screen, which is the baseline density assumed by the system for a "medium" density screen. At runtime, the system transparently handles any scaling of the dp units, as necessary, based on the actual density of the screen in use. The conversion of dp units to screen pixels is simple: px = dp * (dpi / 160). For example, on a 240 dpi screen, 1 dp equals 1.5 physical pixels. You should always use dp units when defining your application's UI, to ensure proper display of your UI on screens with different densities.
It's the image resources or bitmaps which are provided for various densities
To generate images, you should start with your raw resource in vector format and generate the images for each density using the following size scale:
xhdpi: 2.0
hdpi: 1.5
mdpi: 1.0 (baseline)
ldpi: 0.75
Hope this helps.
values folder containing dimens.xml file in which whatever screen size you
specified, it is consider as baseline as per google doc means 10dpx1 as per your question..
now you set this size for different devices than procedure is like following.. create folder for different Screen Size
1) values->dimens.xml [default as per base line hdpi] 10dp x 1.0
2) values_sw320dp ->dimens.xml [xhdpi] 10dp x 1.5 result set to dimens.xml file of values_sw320dp folder
3) values_sw480dp -> dimens.xml [for xxhdpi] 10dp x 2.0 result set to dimens.xml file of values_sw480dp folder
4) values_sw640dp -> dimens.xml [for xxxhdpi] 10dp x 2.5 result set to dimens.xml file of values_sw640dp folder as like you can set size for all devices as per google document..
here you just need to create folder and inside folder create dimens.xml file for working with different screen size in android.
I am developing an android app that run on every size screen. For this I have created folder drawable, drawable-ldpi, drawable-mdpi, drawable-hdpi and drawable-xhdpi. And for layouts creating folders layout, layout-small, layout-normal, layout-large and layout-xlarge. For values I am creating values, values-small, values-normal, values-large, values-xlarge. This is first time I am working on multiple screen support. And on Internet so many links that explain multiple screen support in different ways. So I have few questions.
There is need of any other folder than these folders?
Am I doing right?
How to convert resolution from ppi to dpi?
And the important thing I am creating app only in portrait mode.
Edit-
First I am creating values folders with ldpi, mdpi, hdpi. But devices belongs to same dpi but having different sizes creating problem. So I decide to create folders like above.
Dp are Density independant pixels and are used to generalise the number of pixels a screen has. These are generalised figures taken from
http://developer.android.com/guide/practices/screens_support.html
xlarge screens are at least 960dp x 720dp
large screens are at least 640dp x 480dp
normal screens are at least 470dp x 320dp
small screens are at least 426dp x 320dp
Generalised Dpi values for screens:
ldpi Resources for low-density (ldpi) screens (~120dpi)
mdpi Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.)
hdpi Resources for high-density (hdpi) screens (~240dpi).
xhdpi Resources for extra high-density (xhdpi) screens (~320dpi).
Therefore generalised size of your resources (assuming they are full screen):
ldpi
Vertical = 426 * 120 / 160 = 319.5px
Horizontal = 320 * 120 / 160 = 240px
mdpi
Vertical = 470 * 160 / 160 = 470px
Horizontal = 320 * 160 / 160 = 320px
hdpi
Vertical = 640 * 240 / 160 = 960px
Horizontal = 480 * 240 / 160 = 720px
Edit - adding xhdpi as they are becoming more popular
xhdpi
Vertical = 960 * 320 / 160 = 1920px
Horizontal = 720 * 320 / 160 = 1440px
Keep it simple silly
You are already aware about the usage of different folders to provide alternative resources and images to the application.so just go with it.add it to your application.
and now the next step is,
Just design your layout files and look at its Graphical Layout for Preview All Screen Sizes.
Now,Check->Analyse->Change if required
And you're done :-)
values-w360dp
values-w360dp-xhdpi
values-w360dp-xxhdpi
drawable-w360dp
for better reference , read this thread.
http://developer.android.com/guide/practices/screens_support.html
public static int convertDpToPx(int dp,Context context)
{
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
return (int)px;
}
public static int convertPxoDp (int pixel,Context context)
{
float density = context.getResources().getDisplayMetrics().density;
int minHeight = (int) (pixel*density + 0.5f);
return minHeight;
}
There is need of any other folder than these folders?
There is no "need" to put any of the extra folders actually. Create them only if you need them and only if you want to provide a different layout/resources for the specific device. For example if you have a list view whose items open a detail view (activity) on a phone, you might want a separate layout for tablets(xlarge for example) that has only 1 activity with 2 fragments side by side.
Am I doing right?
Can you test it now? Do you have any problems running your app on different devices?
How to convert resolution from ppi to dpi?
Can't give you an exact formula, but you can find more info about DPI and PPI in wikipedia.