its simple my doubt.
The app have 4 directories(ldpi, mdpi, hdpi, xhdpi) with same images but different dpi . For mdpi is 160dpi, the one im using atm.
What happens with the images i download from the web? i have a news reader and that means each new have one image at least. And i want to have a decent image for all the smartphones.
Do i need different type of images or just download the same for all?
Can i know which resolution is best for each particular smartphone?
I couldn't find the "official" way to handle this so i dont know if its important dpi for images that we plan to download.
Regards!
ldpi means ~120dpi,mdpi means ~160dpi, hdpi means ~240dpi. xhdpi means ~320dpi.
you can follow 3:4:6:8 ratio for ldpi:mdpi:hdpi:xhdpi for resources.
Now you can have different images for all the resolution it is better and there must be no problem. If you cant have different images for all then have a image for xhdpi and runtime you can resize the image depending on the screen resolution.
YOu can use below sample code to know the screen resolution at runtime::
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch (metrics.densityDpi) {
case 120:
//your stuff
break;
case 160:
////your stuff
break;
case 240:
///your suff
break;
case 320:
//your stuff
break;
}
sample code to resize the bitmap::
Bitmap mIcon_val = your bitmap;
Matrix matrix = new Matrix();
matrix.postScale((float)newwidth/mIcon_val.getWidth(), (float)newheight/mIcon_val.getHeight());
Bitmap resizedBitmap = Bitmap.createBitmap(mIcon_val, 0, 0, mIcon_val.getWidth(), mIcon_val.getHeight(), matrix, true);
now you have the new bitmap new width and height you can use it.
If you want to construct a great app, you need to manage every image to fit the right smartphone, it wont look nice if you download the same image for all.
For more info go:
Supporting Multiple Screens
Related
I've a Photo gallery in my app. The set of pictures are stored in the drawable folder. I'm making use of ViewPager when the user swipes through the images.. What is the width and height in pixels and dps for xhdpi, hdpi, mdpi??
I know that the Android documentation says px = dp*dpi/160.. but I'm still confused about what should be the pictures download pixels so that it fits in all screen sizes??
There isn't one magic size that guarantees that it fits all screens perfectly. There are more than one screen size that fall under each density.
You should look at making your layout scale well on as many devices as possible. In your case it sounds like you shouldn't be focusing on an a specific pixel size, but rather how to display correctly on the common screens and gracefully display on less common ones. That being said I would do the following:
I'd look at the dashboard here. I'd make layouts targeting first targeting hdpi with a normal screen size(50.1% of the market) followed by xhdpi(25.1%) with a normal screen size, followed by mdpi(11%) normal screen size. Check table 3 on this page for common screen sizes for those values. Since you will be most likely using an image view make sure to check out the scale type attribute to help handle when the image view isn't at
As a side note(maybe useful later)if you are having difficulties translating sizes between densities and raw pixel values use this calculator.
Use following function which give you height and width of current display
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
deviceHeightPix = displaymetrics.heightPixels;
deviceWidthPix = displaymetrics.widthPixels;
based on this, you can pass data on server to fetch relative images.
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;
}
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;
}
I have created multiple bitmaps - one for each folder (mdpi, hdpi, ldpi). Can someone show me some code or point me to the appropriate method that will allow me to detect which resource Android decided to load.
Thanks,
Get the densityDPI from DisplayMetric and check it against predefined constants
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch(metrics.densityDpi)
{
case DisplayMetrics.DENSITY_HIGH: //HDPI
case DisplayMetrics.DENSITY_LOW: //LDPI
case DisplayMetrics.DENSITY_MEDIUM: //MDPI
}
This is available in the bitmap itself -- http://developer.android.com/reference/android/graphics/Bitmap.html#getDensity()
If you are loading this through the higher level Resources.getDrawable() API, you won't have a Bitmap but just an abstract Drawable. If you can guarantee the resource will always be a bitmap (not a nine patch or other such thing), you can cast this to a BitmapDrawable and get the Bitmap from that.
If you are doing this for production code, I would be a little uncomfortable with this since generally an app should either let the framework take care of density, or take care of it all itself (by for example putting the bitmaps in drawable-nodpi). If you are playing games with bitmaps base on loaded density, you may shoot yourself in the foot. Or you may be fine, since I don't really know what you are doing. :)
I'm not sure what can do with code but for testing purposes I added a small icon called resolution.png that had a version in the ldpi which had the letter 'l' in it, the version for mdpi had a letter 'm' in it and the version for hdpi had the letter 'h' in it. That way you can see which version of the resources are being loaded.
I test with it commented out in the layout most of the time and un-comment it when I want to investigate.
Load a Bitmap directly and compare it with the one loaded via resources:
Resources can be accessed as raw data: use AssetManager.open(..)
Then you can use BitmapFactory.decodeStream(..) to create a Bitmap from the data stream.
I have problem with displaying bitmap image on imageview on high density screen (480x800). When the bitmap image loaded from file on sdcard, the image does not scale to fit hdpi screen. On medium density screen it works normal (320x480).
public static Bitmap getBitmapFromFile(String src) {
File file = new File(src);
if (file.exists()) {
return BitmapFactory.decodeFile(src);
}
return null;
}
mImage.setImageBitmap(Util.getBitmapFromFile(filePath));
Screenshoot on hdpi & mdpi
http://202.148.2.34/~lorenz/iview.jpg
Try adding a scale type to it
mImage.setScaleType(ScaleType.FIT_XY);
There are lot of scaling type available. Check which one suits you.
This is an old question but I think there is an easier way to do this. It seems that when you load a bitmap from an external source (one not in your /res folder) the Android framework will treat it as if it was meant for the baseline device (ie mdpi). Therefore it looks great on a 320x480 mdpi screen, but not as much on an hdpi screen.
Now the system normally should scale for this on an hdpi screen by a factor of 1.5 (unless you supposedly you set a density in the bitmap object, but I don't really know how that works) but since you used the method setImageBitmap() the bitmap is not scaled, leading to your problem.
Supposedly if you use the method setImageDrawable() and wrap the bitmap in a Drawable the bitmap will be autoscaled just like you wanted.
I haven't tried this, but apparently this guy had the opposite problem of you.