I'm trying to make an activity with an image that is the same height as the screen. I tried going to easy route, and just using a really big image and then scaling it down within the app, but when I run it on a device with a smaller screen, I get an error saying the device ran out of memory. I was hoping to make several drawable folders for each dpi (drawable-mdpi, drawable-hdpi, etc.). I looked up the pixel dimensions for splash screens, but when I resize my image to fit those dimensions (https://stackoverflow.com/a/15744389/5909429), the image only fills about half the screen on my smaller device.
What dimensions should I actually use, or am I using the drawable folders wrong?
[...]or am I using the drawable folders wrong?
Yes and no. I don't know about any "perfect" values for your picture dimensions, and I doubt that there are any, due to the fact that there are too many different phones to support.
The usage of dpi ensures that everything has the same size. If you were to put a ruler on your screens on a xxxhdpi and a ldpi device, both pictures would be the same size. This is dpi.
What you are trying to do is filling a phone screen. This has not much to do with dpi, but is about the actual pixel size of the screen. If you have a 1920x1080 phone display, you want an image with the same resolution. This does not say anything about dpi or screen density, and it has frankly nothing to do with it.
To properly scale down your image—and not running into OOM—you can either use a designated image loading library, like Glide, or Picasso, or you can take a look at BitmapFactory which lets you supply a inSampleSize to load the image in the size needed yourself. The official documentation can be found here at Loading large bitmaps efficiently.
Related
I have been looking around and can't find a positive answer to this. For images, do we use hard-coded dp for the layout width and height or do we use wrap_content? For example, say I have an imageview with an icon as its image. If I use wrap_content, the image is too big, and there is no way to resize it (image was made using xxhdpi in mind). If I set the dp manaully then the image doesn't scale with the device if its screen is larger (or does it, I'm not sure if it still does?).
I want to know the workflow we're suppose to follow, I have read all the documentation but it's vague in terms of scaling images. I have an image for each of the various screen sizes (hdpi, mdpi, etc.).
Questions
If I hardcoded the width and height, does android still use those
images (hdpi, mdpi, etc) for different screen sizes?
Is hardcoding the width and height bad practice, if so, what is the
alternative to resizing the image?
What if we hardcoded the size for each screen resolution? So for
example, I would use 200dp x 200dp for tablets and 100dp x 100dp for
phones when hardcoding the width and height of an image. Is this a
good approach?
What is the best workflow to follow when working with images? Should
I create a different size of an image for each screen resolution?
Should I use one large image and then hardcode the size for each
layout?
Is there a website or program in which I can provide an image and it automatically comes up with the various screen density images? For example, I upload an image and it will give me an mdpi, hdpi, hdpix, and etc images for it. I have looked around, but can only find programs that work with icons, not images.
You should be able to rely on the android system to scale your images appropriately. Check out the Dev docs for various scaling methods
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
I have an application that uses ImageViews to show some pictures. The image sizes are 320x480px.
I use some animation to move these pictures to the center of the screen and when the phone has the resolution of 320x480, it works great.
However, when I tried it on emulator with the resolution of 240*320, there were some problems:
The ImageView is still 320x480 so it looks way too big
The animation that uses the screen resolution can't move the pictures to the center, it is at least 20-30 px off
I learned the when dealing with pictures, Android dynamically changes resolution of them to make the images fit in. How could I set that these images should be resized according to screen resolution?
It's hard to say what's wrong without seeing any code. Android resizes images from res/drawable according your screen resolution (ldpi, mdpi, hdpi, etc.). If you place pictures in res/drawable-nodpi, they will not be scaled. You could also use the density dependent folders res/drawable-ldpi, res/drawable-mdpi, res/drawable-hdpi etc. You should definitely read the docs here.
I believe that android:adjustViewBounds="true" and android:scaleType="fitCenter" is what I needed. The ImageViews are scaled down to 240x320 and the animation works well.
Interesting that the upscaling is not proper. When I used in the emulator at 480x800, my ImageView is scaled up to 480x720 so I get black edges. Any idea for that?
I know that the title makes it sound like it is a duplicate, but I think I have a very specific situation here that I can't solve from all of my searches.
First, I have images that are specifically sized based off of a specific monitor (Yes, monitor. Not handheld device's screen). The images are based off of these specific settings:
1600x900 20" monitor at 96ppi
Now, all of the images must be sized in millimeters (they are square images btw, so Height=Width). Using these specific settings as a determining factor, 1mm = 3.78px. So, my images are sized using this. For example, for an image to appear as 65mm, I size the images to 246px. I tested this in Photoshop using these settings, and measuring the image on the screen did in fact come out correct.
So now in my Android application, I load up these images into ImageViews to be displayed. This is where I am stuck. The device is an MDPI device. If I load the images into the MDPI drawables folder, the images appear too large on the monitor. Using my above example, I convert the Drawable to a Bitmap and dump the Height of the image to my log. This is correct and shows 246px, but for some reason it is measuring well over 85mm instead of 65mm.
If I load all of my images into the HDPI (yes, I know it is an mdpi device so it will be sized by the Android OS), the height of the image (using my example) dumps as 164px and appears at roughly 50mm. This is more explainable, but still I am still confused on how to get these images to appear as they did in Photoshop.
So my question is, what is the best way to programmatically size the ImageView to be the exact size of the image? For my example, I need to find out why my 246px square image (at 96ppi) is not showing up as 65mm like it should.
Because these ImageViews are generated programmatically, I have tried the following two things:
Set the ImageView Height and Width (using LayoutParams) to the height of the image (246px). I did this thinking WRAP_CONTENT was not acting as it should.
Used ImageView.ScaleType.CENTER to try and make sure the ImageView is sized exactly to the image.
Neither of these things seem to have effected the output.
UPDATES:
I have verified that my device is a MDPI device. This means that there is not DPI to PX conversion (or vice versa) necessary because of the 1:1 relationship. Somewhere, the sizes are being increased and I cannot determine where. As I indicated in the comments for the answer below, when I pull my Drawable and convert it to Bitmap, it pulls the EXACT pixel Height that I made it. I am starting to figure out the percentage of size difference from what it should be (65mm vs 85mm) and it works out to be 23.529%. I am scaling my bitmaps subtracting this value, but it ruins the quality of my image.
I am beginning to give up.
The device I am utilizing is an MK802III Rockchip Device (Amazon Link)
Android modifies all images for display with the following formula:
px = dp * (dpi / 160)
Where "dpi" is the screen density in dots-per-inch of a device's display.
Additionally, Android looks through a hierarchy of drawable folders when deciding which image to display. As we all know, an HDPI device will use an image from the drawale-hdpi folder while an MDPI device will display the same named image from the drawable-mdpi directory.
However, when an MDPI device cannot find an image in the drawable-mdpi directory, it will eventually choose from the drawable-hdpi folder, but it will down-scale the image for display on the MDPI screen.
This explains why your image appears smaller when you saved it in the drawable-hdpi folder.
But, it does not explain why the image appears too large when correctly placed in the drawable-mdpi folder.
It so happens that:
65mm ~= 85mm * (120 / 160)
50mm ~= 85mm * (120 / 240)
This is the scaling that I would expect for your images if your device were LDPI (120dpi) instead of MDPI (160dpi) as reported.
I hate answering my own question, but I am just going to update everyone what I did. If someone comes up with a better solution, I am all ears. I had to force this along because I am on a tight deadline.
I created a dummy application that dumped boxes that I could measure. Using these, I determined that 1 millimeter is 3 density pixels. Let me repeat that, 1mm = 3dp.
Using this value, I resized all of my images (utilizing a PHP script) to this constraint. All of my images are appearing as normal. 195dp = 65mm, and it appears as such.
Like I said, any explanation as to why I had to do this and you get an upvote and answer.
I am kind of confused about managing graphic resources in Android.
Tried to read this doc but It only confuses me more. Can anyone give me some example of how should I handle the following case?
Lets assume that I have an image in my layout that will be scaled to fill screen width. What image sizes (in pixels) should I produce and what configuration qualifiers (drawable-{qualifier}) should I apply to those resources to cover all major dpi and screen sizes (both for tablet and handset)?
Thanks.
If you want to have an image, that is supposed to fill the screen it is best to use 9-patch images. This way your image can automatically scale to fit the device. Because even if an image has the correct density, the actual screen size can vary. For example a smartphone and a tablet can both be hdpi, but have completely different screen sizes (and actual pixel count).
So the easiest way to target most devices, when it comes to images that are supposed to fill up the full width of the screen is to have a 9-patch image and create ldpi, mdpi, hdpi and xhdpi versions of it. This way the image will automatically be choosen depending on the density and then stretched to fit the device.
The android sdk also provides a tool that helps with creating 9-patch images http://developer.android.com/tools/help/draw9patch.html
I have images that need to scale to the screen's size. The images will also have text in it that needs to be translated to a second language. So there will be two versions of each image to start, one for each language.
Google recommends having an image resource per density. So I'd take my two images and multiply them by four: xhdpi, hdpi, mdpi, and ldpi. But then Google say to have different image resource for different screen sizes. This multiplies my images by four again: xlarge, large, normal, and small. I don't want to create 32 copies of every image!
I'm wondering if there is anything wrong with making the images for xlarge screens and xhdpi densities only. IE – Best quality. Let Android scale down the images for lower densities per its standards for dp units. And when I draw on smaller screens, I could use the Canvas class to scale down further. I could cache the resulting scaled Bitmap object for use every time it needs to redraw the bitmap to avoid expensive scaling computations running over and over.
Is there any drawback to doing this? Or is there a better way to avoid making so many copies of the same image?
There will be a performance penalty in downscaling large images on smaller (low-end) devices. Whether this will be noticeable depends on the number of images you have to show.
The same holds, mutatis mutandis, for memory.
I create bitmaps only for the highest xhdpi pixel density, and then test on other screen types.
If a bitmap looks bad on some lower-density screen, I remake it specifically for that density. And this happens quite rarely...
Also, making special bitmaps for different screen sizes (small/xlarge) is not needed - just make your ImageView-s smaller/larger - image scaling is not a slow operation, so in most cases you don't need to worry about it either (unless your bitmaps cover the whole screen).