I am working on an android application. i have used different layout folder. Like layout,layout-large,layout-xlarge. So that it can adjust for all resolutions. But i am setting images dynamically in activity. How can i change them according to screen resolution? How too big image will replace smaller if we change resolution?
Android works with density buckets, which go from l(low)dpi to xx(extra extra)h(high)dpi.
You want to create different versions of your images in folders as
drawable-ldpi
drawable-mdpi
drawable-hdpi
drawable-xhdpi
and drawable-xxhdpi if you want to support the Nexus 10.
That's kind of loose from the layout-large folders, which enable you to define different layouts for different sizes.
2 pretty different things, which you can read much more about at
screen practices in Android.
=======
Edit; Seems this wasn't exactly the question.
If you're doing it 'the right way' the Android system will choose the correct image for you, even when adding them dynamically (you can still call R.drawable.my_image from java code).
If for some reason you do have to choose, you can simply check for the current density with something like (a little outdated);
public String getDensity() {
String density;
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
// will either be DENSITY_LOW (120) , DENSITY_MEDIUM (160) or
// DENSITY_HIGH (240)
switch (dm.densityDpi) {
case 120:
density = "ldpi";
break;
case 160:
density = "mdpi";
break;
case 240:
density = "hdpi";
break;
// use hdpi as default, because flurry shows this will be suited for
// most of our users.
default:
density = "hdpi";
break;
}
return density;
}
Related
I have an app with different versions for screens (small, normal, largue, and extraLargue XML files) each with its XML designed for each type, but I found a Huawei phone with this screen 3.5" HVGA 320x480.
My question is, should not the UI of Android use the small configuration for this screen? Is that the app when running on this phone uses the normal configuration as if it were a nexus4 4.7" 768x1280 as I change that?
I tried to create various types of screen (create other) with multiple configurations without optimal result.
Assuming the 3.5" measurement is on the diagonal, this works out to about 165 dpi which falls into the mdpi (or normal screen size) bucket according to Android's Supporting Multiple Screens guide.
DPI = sqrt(w^2 + h^2) / d
where
w is the width of the display in pixels
h is the height of the display in pixels
d is the physical diagonal measurement of the display in inches
It is quite simple.
You need to add different UI and make controls VISIBILE and GONE.
int appScreen = getResources().getConfiguration().screenLayout &
Configuration.SCREENLAYOUT_SIZE_MASK;
switch(appScreen) {
case Configuration.SCREENLAYOUT_SIZE_LARGE:
UIControl.setVisibility(View.GONE);
break;
case Configuration.SCREENLAYOUT_SIZE_NORMAL:
UIControl.setVisibility(View.GONE);
break;
case Configuration.SCREENLAYOUT_SIZE_SMALL:
UIControl.setVisibility(View.GONE);
break;
default:
UIControl.setVisibility(View.GONE);
}
I thought I was successful in adjusting for different screen sizes(I was using the eclipse emulators and creating different screen sizes to test my app) but when I test my app on actual devices the result of my app varies. for example for a large screen size I set my emulator to a Nexus S and it will work and look fine, but then I try on an Alcatel One Touch Fierce(real device) which is still considered a large screen size the app play is just a little bit off, then I play it on another device which is also considered a large screen size the app will play just like the emulator. So i guess mt question is why? a samble of how I'm checking for different screen sizes is below:
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
switch(displayMetrics.densityDpi)
{
case DisplayMetrics.DENSITY_LOW:
// layout for small sized devices.
break;
case DisplayMetrics.DENSITY_MEDIUM:
// layout for medium-sized devices.
break;
case DisplayMetrics.DENSITY_HIGH:
// layout for large devices.
break;
case DisplayMetrics.DENSITY_XHIGH:
// layout for really large devices.
break;
Before your case statement, try to print the density value like this:
Log.i("Sushil", "displaymetrics.densityDpi : " + displaymetrics.densityDpi);
And check if it matches with any of your defined case statement. Else add new case statements, it should work. Few more defined cases are :
DisplayMetrics.DENSITY_TV
DisplayMetrics.DENSITY_XXHIGH
Hope this helps.
i don't see any thing wrong with the outcomes. if you run an app designed on a phone emulator-----on a tablet, the layouts will not match.
you have to decide if you wanna support different screen sizes or not if you do, then you'd have to create diffrent layouts for different screen sizes and set the corresponding layout in the OnCreate method of your Activity.
here is how to check if the device is a tablet or a phone:
if(isTablet==true){
setContentView(R.Layout.my_tablet_layout);
}else{
setContentView(R.Layout.my_phone_layout);
}
public boolean IsTablet() {
return (getApplicationContext().getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
Is it possible to use common hdpi folder for all screen densities? I have quite a lot images. If I make specific copies to folders drawable-hdpi, drawable-ldpi, drawable-xhdpi, ... but it takes huge data (backgrounds, bitmaps).
Is it possible to set only one drawable folder for all devices and then rescale according to a specific device programmatically?
I think about this code to get display size of the scree:
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
Then I will get display density of the device, something like this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
density = metrics.density; // 1 - 1,5 - 2 .....
The I will recalculate size of imageview with density:
ImageView logo = (ImageView)findViewById(R.id.logo);
LinearLayout.LayoutParams logo1 = (LinearLayout.LayoutParams) logo.getLayoutParams();
logo1.width = (int)(logo.getWidth()*density);
logo1.height = (int)(logo.getHeight()*density);
logo1.leftMargin=(int)(logo1.leftMargin*density); // for margin
logo1.topMargin=(int)(logo1.topMargin*density); // for margin
logo1.rightMargin=(int)(logo1.rightMargin*density); // for margin
logo1.bottomMargin=(int)(logo1.bottomMargin*density); // for margin
My main problem is I need to have all proportions of graphic same on all devices. It means I must recalculate imageViews accroding to the screen size.
Is this a right way to get density independent screen? How does android work on other devices if only hdpi folder contains files. Does it take files from this folder? Can I set one common drawable folder to all densities?
I would strongly (strongly) advise against doing this. However, if you want the system to rescale your image assets, design them for mdpi (the baseline density) and put them in drawable/.
That said, you need at least mdpi and hdpi to get reasonable scaling (since hdpi is 1.5x mdpi, scaling algorithms produce worse results than for the other conversions from mdpi).
Make sure you've read and understood Providing Resources and Supporting Multiple Screens before you start dealing with resources.
P.S. The layout solution is wrong for a few reasons (e.g., setting margins instead of size) but it's also the completely wrong thing to do. Don't do it!
I want to make game for supporting all Android device(Tablets and phones).I can get screen size through coding.
Do I have make 3 0r 4 layouts small , medium and large?
Which size for small , medium , large and extra large?
Is there any other way to set layout for all devices?
Here is the Android documentation for what you need:
http://developer.android.com/guide/topics/resources/providing-resources.html
You can use the screen-size, screen pixel density, or other things to determine how to separate your layouts.
You can specify different layouts (and you should try to). Different sizes may use the same layout. What layout the device ends up using depends on a set of rules.
So for example if you wanted to use screen size, you would want to make folders under your res folder called layout-small, layout-medium, layout-large, layout-xlarge. This is because layout is the default folder for layout resources, and then you add a -. In this case, small, medium, large, or xlarge.
Edit: Alex's link above might be what you're looking for. My link is more about HOW to do it, but Alex's link is more about how to do it WELL. I wasn't sure what you were asking exactly.
(1) One way to support all the layout sizes is to put images of suitable sizes into drawable-hdpi, drawable-mdpi, drawable-ldpi and drawable-xhdpi. The image for a device of a particular screen size will be automatically picked by Android runtime system. In this approach you will NOT have to make different layout files for each size.
(2) Second way to achieve the same is to dynamically detect the size(density) of the device and then set the layout accordingly, which can be done like this:
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
switch(displayMetrics.densityDpi){
case DisplayMetrics.DENSITY_LOW:
// your layout for small-size devices.
break;
case DisplayMetrics.DENSITY_MEDIUM:
// your layout for medium-size devices.
break;
case DisplayMetrics.DENSITY_HIGH:
// your layout for big-size devices.
break;
}
In this approach, you MAY have to make different layout files for each size separately.
So on device there's the drawable directories for hdpi, mdpi, ldpi etc...
Now lets say I want to download images from the internet to view in the app (on the fly).
Can I have the three different densities of image available for download? Is there some way I can check if the current device is hdpi/mdpi/ldpi and download the right resolution accordingly? Or is it much more simple than that?
I guess if I download a high res image onto a hdpi phone then it will assume its a mdpi image that just has larger dimensions than intended?
Thanks
This is how you get the density programatically
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch(metrics.densityDpi){
case DisplayMetrics.DENSITY_LOW:
break;
case DisplayMetrics.DENSITY_MEDIUM:
break;
case DisplayMetrics.DENSITY_HIGH:
break;
}