Android perfect UI: fighting with dithering
Everyone who tries to use gradients in the images on mobile device comes to the problem: how to make gradients look nicely? The answer is simple – dithering.
I will try to give some tips here about dithering images for Android devices. This is updated version of my previous post about dithering.
First of all you can make dithering in 2 ways:
- Dither images from the code or XML on the fly
- Pre-dither images in image editor software
Dither images from code
Let’s consider an example: you are trying to make a perfect button for your perfect UI.
You made a superb sketch in (let’s say photoshop) and want to transfer it to your G1 device. In the image editor software the button looks nice:
Then try to insert it to the Android Activity layout as ImageView with android:src.
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/b1" />
It looks… horrible isn’t it? Let’s try to apply dithering from XML.
Create new drawable:
<?xml version="1.0" encoding="UTF-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/b1" android:dither="true" />
and use it for the ImageView above. The result:
Because dithering in Android is applying only for stretchable or tile images. Why? I don’t know. If you know – please write me. I will take a look at the platform code later).
Then let’s add tile mode:
<?xml version="1.0" encoding="UTF-8"?> <bitmap xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/b1" android:tileMode="repeat" android:dither="true" />
And magic comes to your Android device:
You can also get the same result if you make a nine-patch image like this one:
apply dither from XML and set drawable as ImageView background
<?xml version="1.0" encoding="UTF-8"?> <nine-patch xmlns:android="http://schemas.android.com/apk/res/android" android:src="@drawable/btn_red" android:dither="true" />
or you can even do the same from the java code:
Dithering images in dialogs
If you will try to do the same things in Dialog activities with transparent background – you would probably fail. Because when you have transparent dialog background the platform doesn’t know about underlying layer when rendering your image.
But here is another solution! You can set the flag in the Dialog window manager.
That works like a charm
Of course sometimes you have to pre-dither your images. For example you a painting non-stretchable image on canvas in onDraw method and cannot dither it on the fly. Or you want to do this for performance reason.
You can simply apply 1% noise in photoshop:
you will get something like this:
Or you can use special plug-ins like 5-6-5 (http://www.telegraphics.com.au/sw/)
Plug-in is better that just a noise because you get PNG image with reasonable size.
Original image: 1218 bytes
1% noise: 14960 bytes
5-6-5 plug-in: 2026 bytes
And render on device.
1 – without dither
2 – program dither
3 – dither with noise
4 – 5-6-5 plug-in dither