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:

  1. Dither images from the code or XML on the fly
  2. 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:

original button in photoshop

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" />

android - no dither

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:

Android dither with xml
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:

Android tile and dither

You can also get the same result if you make a nine-patch image like this one:

nine-patch android dither

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:

pre-dither - apply noise in photoshop

you will get something like this:

pre-dither - apply noise in photoshop

Or you can use special plug-ins like 5-6-5 (http://www.telegraphics.com.au/sw/)

5-6-5

5-6-5 dithering

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.

different android dither

different android dither

1 – without dither
2 – program dither
3 – dither with noise
4 – 5-6-5 plug-in dither

Happy dithering!

  • Share/Bookmark

Comments (8)

tigerJanuary 29th, 2010 at 11:56 am

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 :

villain_dmJanuary 29th, 2010 at 12:00 pm

it should work for backgrounds. please repost your code

tigerJanuary 29th, 2010 at 4:33 pm

I’d love to but it seems I cannot post any code here…
Which tags should be used so that the blogs accepts it ?

JeremyFebruary 6th, 2010 at 2:08 am

Thanks.

JeremylvFebruary 8th, 2010 at 10:29 pm

I wish this was explained in the Android Dev Guide, I’ve been looking for something like that for ages! Thanks!

Maxim YudinMarch 5th, 2010 at 2:38 pm

Хорошая статья, в свое время тоже пытался бороться с градиентом, делал через фотошоп и потом растягивал через nine-patch, благодаря тебе узнал что можно просто использовать аттрибут dither, буду теперь твой блог тоже читать.

Marco SchmitzJuly 7th, 2010 at 7:52 pm

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?

villain_dmJuly 8th, 2010 at 12:30 am

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.

Leave a comment

Your comment