I am writing an app that has a lot of images (about 200) which are different items that you can select and order. So far I have been using Glide to load the images from file. To support different resolutions, I made a image of the item with my smartphone and converted them into the 5 different Android resolutions in the folders drawable-mdpi, drawable-hdpi, drawable-xhdpi, drawable-xxhdpi and drawable-xxxhdpi.
The problem is that the original image has as size of 4,2 MB and all 5 images together just for one item for the different resolutions have a size of 18 MB (0,7 MB, 1,5 MB, 2,5 MB, 5,6 MB and 7,8 MB). If I now do this for 200 images, I will have to store 3,6 GB of images within the app. Thus, the size of the app would be extremely big.
So I would like to know what is a good way of dealing with so many images in an app? Is there a way to include multiple images for different resolutions while still having an app whose size is not enormous?
Follow the following steps:-
First of all, compress all of your 200 images. I will suggest you to use this website or any other.
After that add all the images to your drawables.
Convert all of your images to 'webp' using Android Studio.
1st Screenshot
Set the quality percentage according to your desire
2nd Screenshot
See the difference of image sizes
3rd Screenshot
In this way, quality will not be much compromised & large size problem will be solved.
-> Drawable Folder Position
loadGlide(R.drawable.testing, imageView)
Call this function from everywhere
Kotlin
private fun loadGlide(resId: Int, imageView: ImageView) {
Glide.with(context).load(resId).with(imageView)
}
Java
public static void loadGlide(int resId, ImageView imageView) {
Glide.with(getContext()).load(resId).with(imageView);
}
I took it with my smartphone camera and generally the images there have a resolution of 4032*3024
Have just one copy of the image, in res/drawable-anydpi/ to use it for any density.
The density-specific drawable system is designed for much smaller images than the full screen (icons, logos, etc.).
Related
java.lang.OutOfMemoryError
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at nis.animation_door.Page5.onCreate(Page5.java:32)
Basically it tries to rescale/resize background images i m using.
the images have 1024x768 size
I use SonyXperia tablet z(real display size - 1920x1128px)
Following similar question answered on SO I have put all background images into drawable-hdpi,ldpi etc folders
At runtime, Android resize's images based on need (based on the screen size and resolution). It uses Bitmap's for doing the resizing internally. Which, obviously, is very memory intensive (kinda allocates memory like crazy). One quick way to fix such issues can be, that you copy all drawable files to drawable-ldpi, mdpi, hdpi folders. This way android will just pick up the files from these folders and not resize them.
This did not help, I suspect because even if you put same images into ldpi folder, you have to resize/rescale them manually.
My question - if make my bkg images exactly same size as my real device - 1920x1128, will it help? any other suggestions?
I have a set of 4 images I plan to display at the first launch of my app inside of a ViewPager. Each of them is 1MB, so that's 4MB total
I want these images to be shown for any density screen.
Where should I place these images?
In which size?
Will duplication increase the size of my app?
Maybe a more efficient way to do it? (one location for these drawables)
The closest I've found is http://romannurik.github.io/AndroidAssetStudio/ but it's only for icons
Thanks!
Q1.2. Location: /res/drawable. You can have many version of those images and place them in different folder: drawable-hdpi, drawable-ldpi... For better result, please read http://developer.android.com/guide/practices/screens_support.html
Q3. Duplication will definitely increase the size of your app. But common users will possibly ignore its size is not ridiculously big.
Q4. You can store only one image for every screen size, but you need more coding work to scale the drawable to fit the screen of different device. For better result please read: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
I am wondering what your thoughts are on which is the better strategy when designing UI for android devices.
Which do you preffer:
Setting the size of elements in the XML files, for each denisty (and size when needed), using only one set of images (xxhdpi images) which will scale down when needed.
Pros - smaller apps (less resources)
Less work on images for UI people.
Cons - more work on XML files (a whole lot sometimes)
Create images for each denisty (and size if neede) using Wrap_content most of the time.
Pros - Only one set of XML layout files.
Cons - more images and larger sized apk.
more work on images for UI people.
What other approaches are you using?
Thanks!
I think you are misunderstanding what Android is doing when it scales images that you do not provide. The Android docs state:
By default, Android scales your bitmap drawables (.png, .jpg, and .gif files) and Nine-Patch drawables (.9.png files) so that they render at the appropriate physical size on each device. For example, if your application provides bitmap drawables only for the baseline, medium screen density (mdpi), then the system scales them up when on a high-density screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the bitmaps. To ensure your bitmaps look their best, you should include alternative versions at different resolutions for different screen densities.
All this means is that if you do not provide alternate density versions of images, Android will fill in the missing ones (created and the correct proportional size) using the ones you have provided, but at the cost of some quality of the image, since Android is not going to scale an image as well as say Photoshop. If you are concerned with application size, you can consider if the loss of image quality from omitting certain density versions is an acceptable tradeoff in order to make your .apk smaller.
So, #1 and #2 can both use wrap_content, and neither has to set the size of an image manually, unless the image needs to be larger or smaller than the original size (which in that case you should just create the image at the right size). #1 also does not and should not require more layout work. And for #2, saving an image at several sizes is not very much extra work at all.
I personally follow these rules:
Create images for every density (except ldpi / tvdpi - too few devices, I'm ok with the image quality loss on them).
Use wrap_content and match_parent as needed with images.
Only use dp for images downloaded at runtime, where size cannot be guaranteed.
my choice is a mixed one. I create differet images for those which are complex and has a chance of being abnormal for automatic compression. But for usual images I only used the first approach.
i just released my app on android and have problems with customers with high density displays.
i added a debug thing to see what's going in, here is one sample output
Device: Nexus 10 Android version: 4.2.2
DisplayMetrics{density=2.0, width=2560, height=1504, scaledDensity=2.0, xdpi=298.275, ydpi=298.823}
MainView w=1900 h=1342
mDrumKitMode=BIG
KitView w=640 h=1266 x=1920.0 y=0.0
the main view is the music notation area on the left of the screen shot, its 1900 wide (MainView w=1900 h=1342) the drum kit is a bitmap that is 640w and 640 high. somehow, the display is scaling it to be full height of the parent, (KitView w=640 h=1266 x=1920.0 y=0.0). this doesn't happen on displays where density=1.0.
i have no way to test this since i can't get the emulator work on big displays for some reason and i don't have a high density tablet.
does anyone have an idea what could be going on? thanks
and here's another customer with a similar problem
Device: A700 Android version: 4.1.1
DisplayMetrics{density=1.5, width=1920, height=1128, scaledDensity=1.5, xdpi=224.73732, ydpi=224.11765}
MainView w=1260 h=1044
mDrumKitMode=BIG
KitView w=640 h=968 x=1280.0 y=0.0
i think its the scaledDensity=1.5 parameter, maybe i need to do something to disable automatic image scaling, i.e. set scaledDensity=1?
i should add that the entire application is based on exact pixel positions, both for the music notation display and the drum kit display which overlays images on top of the base drum kit image (you can see the drum pedals are in the wrong place on this image too). i don't want automatic scaling as i handle scaling inside the app for different display sizes and user preferences.
i should also add that all my drum kit images are in drawable-mdpi and all the other dpis are empty. this is because i scale images programmatically based on screen size and user preference BUT i think maybe the problem is a need to put some images in xhdpi? i guess i can do that but it will be a lot of work.
PS, i guess i found my answer here http://developer.android.com/guide/practices/screens_support.html
Provide different bitmap drawables for different screen densities
By default, Android scales your bitmap drawables (.png, .jpg, and .gif files) and Nine-Patch drawables (.9.png files) so that they render at the appropriate physical size on each device. For example, if your application provides bitmap drawables only for the baseline, medium screen density (mdpi), then the system scales them up when on a high-density screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the bitmaps. To ensure your bitmaps look their best, you should include alternative versions at different resolutions for different screen densities.
i wonder if simply copying all the -mdpi images to -xhdpi will work?
If you intend for this app to be used across devices you have no choice but to put in images for all the various density folders that exist (xhdpi,xxhdpi, hdpi, mdpi). It's also worth considering that you may want to change the actual layouts you include, to offer different ones for different devices.
Consult the documentation for how to handle this.
http://developer.android.com/guide/practices/screens_support.html
If that creates an apk that's too heavy (I have no idea how many images you have) then you can go the other way and specify a no scaling drawable folder which will just use the images in their native density across devices. It's definitely wrong to use ONLY mdpi unless you intend to support only mdpi devices.
I have a Gallery widget that allows a user to select from a variety of images which I supply with the app. Because of different screen resolutions, I have different size images in different drawable folders. Eg drawable-large has 1280x800 versions of the images, drawable normal has 480x320. This is so the image looks good once selected on all resolutions.
The problem I am having is that the Gallery widget, on large resolutions, ends up using the 1280x800 versions of the images to populate the widget. With around 6 of these images, the VM heap memory becomes too large and the app stops working.
Is there any way to force loading images from a specific drawable folder?
I know I could easily solve the problem by adding extra images to my folders but I don't want to increase the size of my app too much.
You can create aliases to your resources, see http://developer.android.com/guide/topics/resources/providing-resources.html#AliasResources
You can then put all your gallery image that are used by multiple resolution in one place, so as to not have resource duplicate in your folders.