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:

the same.
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:
findViewById(R.id.ImageView01).getBackground().setDither(true);
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.
getWindow().setFlags(WindowManager.LayoutParams.FLAG_DITHER, WindowManager.LayoutParams.FLAG_DITHER);
That works like a charm
Pre-dither images
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
Happy dithering!


hi,
do you have any experience in using an image as a background parameter for a layout..
So will this work for such a case as well and if so could you help out with a piece of code ?
I actually tried this but it didnt work :
it should work for backgrounds. please repost your code
I’d love to but it seems I cannot post any code here…
Which tags should be used so that the blogs accepts it ?
Thanks.
I wish this was explained in the Android Dev Guide, I’ve been looking for something like that for ages! Thanks!
Хорошая статья, в свое время тоже пытался бороться с градиентом, делал через фотошоп и потом растягивал через nine-patch, благодаря тебе узнал что можно просто использовать аттрибут dither, буду теперь твой блог тоже читать.
Thanks for this post. I read it several times, played around with all techniques, but I didnt find a solution. Somehow all techniques aren’t working. Well, on the emulator it looks awesome, but on real devices like Nexus One, G2, Milestone, Experia Mini my gradient still looks awful. Did anyone find other solutions?
Marco, what exactly are you trying to do? post device screenshot or simple project code somewhere
On nexus-like device screen you could probably have another problem with semi-transparent images dithering.