I was wondering if I can change device which decides which layout it should choose or which graphic it should choose/scale. This change should only affect my application of course. Can I set somehow device DPI?
The reason why I'm doing that is this phone: http://www.gsmarena.com/samsung_p1000_galaxy_tab-3370.php it has very bad DPI od 240DPI while it's only 170PPI and should be recognized as 160DPI device.
I have quite big graphic for layout-large which looks great on mdpi, but on hdpi they doesn't fit, they are just to big.
Maybe you have another solution than changing device DPI?
Yes it is possible.
The following will set the dpi to 240. Although you have to refresh the activity somehow e.g. restart application.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.density = 1.5f;
metrics.densityDpi = 240;
metrics.heightPixels = 1104;
metrics.widthPixels = 1920;
metrics.scaledDensity = 1.5f;
metrics.xdpi = 254.0f;
metrics.ydpi = 254.0f;
getResources().getDisplayMetrics().setTo(metrics);
you should create your application
to support with multiple screens.take a look at documentation
and hope these links helps you
Designing for Multiple Screens
Working with Multiple Android Screens
Samsung Galaxy Tab GT-P1000 take layout from layout-xhdpi if this not there then it will look for large.
Try to support multiples screen resolution for your app based on that documentation
you have to Design alternative layouts and drawables for your app
Related
I tried this doing with device dpi. Getting dpi and scaling image accordingly but does not work on all devices. I have written code in cocos2dx framework and tried it on android, devices like xolo and xiomi my note does not display the desired result (image size different from rest devices).
My concept is if one device has 320 dpi and another has 240 dpi than
1 inch = 320 px(in 1st device) = 240 px(in 2nd device)
for android I have used
getWindowManager().getDefaultDisplay().getMetrics(metrics);
metrics.xdpi
metrics.ydpi
and scaled accordingly for each phone
Is it possible that all devices not return correct dpi.
Is this a correct way of doing it?
Is there an alternate solution for obtaining this result?
For some devices xdpi and ydpi metrics are returning wrong numbers and you cannot rely on them. Since API 17 you can also use getRealMetrics(). It should give you accurate values for xdpi and ydpi.
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getRealMetrics(dm);
dm.xdpi
dm.ydpi
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!
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'm trying to get the screen's dpi but so far it isn't working. I tried:
DisplayMetrics dm = new DisplayMetrics();
mainContext.getWindowManager().getDefaultDisplay().getMetrics(dm);
SCREEN_DPI = dm.densityDpi;
But both on Samsung Galaxy Tab 10.1 and on Samsung Galaxy S I9000 the SCREEN_DPI is equal to 160. I also tried SCREEN_DPI = dm.density, but I get the value 1.0 to both cases.
Any help would be greatly appreciated.
Duplicate of this question
Though Android doesn't use a direct pixel mapping, it uses a handful
of quantized Density Independent Pixel values then scales that to the
actual screen size. So the density property will be one of those
constants (120, 160, or 240 dpi).
If you need the actual density (perhaps for an OpenGL app) you can get
it from the xdpi and ydpi properties for horizontal and vertical
density respectively.
Try getRealMetrics() instead:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
This API was officially added in API 17, but in my limited testing it's worked correctly even on 4.0 devices, so it may have been a hidden API before that.
Official documentation here, though there seems to be more reasons that the other API doesn't do what you expect than the text there would imply.
According to #CommonsWare: "Samsung is welcome to categorize them (the devices) to be in whatever density bucket they wish". So, in this case, both devices are in the same density bucket.
All the different resolutions of the different Android products are driving me nuts.
My first android app that I wrote was designed so it supported the three commonly used resolutions: 240x320 (LDPI), 320x480 (MDPI) and 480x800 (HDPI). The 480x854 didn't do any harm to the layout because it has the same width as 480x800.
I've also bought the following devices to test my android apps on:
Samsung Galaxy Europe (LDPI)
HTC Desire Z (HDPI)
Luckily my girlfriend has a HTC Wildfire S (MDPI) so I've got most resolutions covered.
But today, my brother downloaded my app on his new HTC Sensation which has yet another resolution 540x960 (HDPI?). Which didn't show my app as it should and probably the most tablets won't show it correctly either.
What I've did with my first app was read out the density and then set the parameters:
public void set_ui_parameters() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
if(metrics.densityDpi == DisplayMetrics.DENSITY_HIGH){
textSize = 35;
timeWidth = 80;
dayWidth = 110;
moneyWidth = 50;
} else if(metrics.densityDpi == DisplayMetrics.DENSITY_MEDIUM){
textSize = 35;
timeWidth = 53;
dayWidth = 73;
moneyWidth = 33;
} else if(metrics.densityDpi == DisplayMetrics.DENSITY_LOW){
textSize = 28;
timeWidth = 40;
dayWidth = 55;
moneyWidth = 25;
}
}
Besides the parameters I've also created drawables for LDPI, MDPI and HDPI. This works fine for the resolutions described above, but this depends on the screen resolution i.c.w. screen size and fails for, for example the HTC sensatoin with 540x960.
I know that not all the resolutions are used that often, but I would like to support as many as possible. Stats of Screen Sizes and Densities
I've read Supporting Multiple Screens multiple times but didn't found a clear answer to this "problem".
So should I read out the resolution and set the parameters according to the resolutions instead of density? Is this a smart thing to do or how do you cope with this?
Thanks a lot for your information!
You don't have to do that to support different densities. What you do is create different resources folders:
res/values-ldpi/dimens.xml
res/values-mdpi/dimens.xml
res/values-hdpi/dimens.xml
Then Android will decide which file to use. You can have something like:
<!-- in values-ldpi/dimens.xml -->
<dimen name="textSize">25dip</dimen>
and..
<!-- in values-mdpi/dimens.xml -->
<dimen name="textSize">20dip</dimen>
etc. And you shouldn't care about resolution... there are a lot of different resolutions sizes so it would be a hell to take decisions based on that.
Also, if you use dp instead of pixels, you hardly ever will have to create different dimensions files for each density. Of course, sometimes you have to, but it depends on the app.
Only thing you have to do is, that you set android:minSdkVersion to 7 or higher in your manifest file. Is is possible that some views will appear slightly different but app is
applicable and on whole screen.
Now, i'm just guessing here since the rest of the implementation isn't shown, but I'm assuming you are using those derived measurements as px
Take a look at dp. That essentially does all those things you did, automatically, for any device. (Device Independent Pixel)
Don't worry about the slight difference in resolution: 540x960 is only slightly bigger than 480x800. The extra vertical space is easy: it gives you more room for your lists. For horizontal space, as long as you're handling your layouts correctly you'll simply have extra padding (30pix ea) on the sides.
Unfortunately, full-width images (480 wide) are a slightly bigger problem. If you want pixel perfect images, you'll want to use scaleType="center" so the image centers but not scales. If you want full width, you can use scaleType="fitCenter" to make it fill. It will be a bit fuzzy... but so many thing on Android are ;-)
I ran into this problem as well, except my app is a game where there is one SurfaceView canvas that I draw background images and sprites to (similar to LunarLander example).
The way you handle it here is to extend your background image to the largest size you are willing to support (540x960) but you keep all the important things (like buttons, text, information, etc) within a smaller rectangle of 480x800. You can extend the image itself, or just add borders. The key is that nothing important is there.
People with 480x800 phones will see your normal app. People with 540x960 phones will see a little extra border.