December 24th, 2012

Android Tricks: FadeImageView

When used with care, animation can be much more than a mere gimmick—it can improve the quality of the user experience. Subtlety is the key to using animation effectively: the best UI animations are the ones your users don’t notice because they feel natural.

I created a small helper class called FadeImageView that wraps Android’s standard ImageView, applying an automatic fade transition when changing pictures. I have started using this class everywhere that I would normally use an ImageView.

The animated fading effect is particularly nice in cases where a placeholder image is later replaced with an image that is downloaded from the Internet. The result is a smooth transition that makes the change less jarring.

Without further ado, the following is the code:

using System;

using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
using Android.Graphics;
using Android.Views.Animations;
using Android.Graphics.Drawables;

namespace Foo
{
	public class FadeImageView : ImageView
	{
		Animation fadeInAnimation;
		Animation fadeOutAnimation;

		public FadeImageView (Context ctx) : base (ctx)
		{
			Initialize ();
		}

		public FadeImageView (Context context, IAttributeSet attrs) :
			base (context, attrs)
		{
			Initialize ();
		}

		public FadeImageView (Context context, IAttributeSet attrs, int defStyle) :
			base (context, attrs, defStyle)
		{
			Initialize ();
		}

		void Initialize ()
		{
			fadeInAnimation = new AlphaAnimation (0, 1) {
				Duration = 500
			};
			fadeOutAnimation = new AlphaAnimation (1, 0) {
				Duration = 100
			};
		}

		void DoAnimation (bool really, Action changePic)
		{
			if (!really)
				changePic ();
			else {
				EventHandler<Animation.AnimationEndEventArgs> callback = (s, e) => {
					changePic ();
					StartAnimation (fadeInAnimation);
					fadeOutAnimation.AnimationEnd -= callback;
				};
				fadeOutAnimation.AnimationEnd += callback;
				StartAnimation (fadeOutAnimation);
			}
		}

		public void SetImageBitmap (Bitmap bm, bool animate)
		{
			DoAnimation (animate, () => SetImageBitmap (bm));
		}

		public void SetImageDrawable (Drawable drawable, bool animate)
		{
			DoAnimation (animate, () => SetImageDrawable (drawable));
		}

		public void SetImageResource (int resId, bool animate)
		{
			DoAnimation (animate, () => SetImageResource (resId));
		}

		public void SetImageURI (Android.Net.Uri uri, bool animate)
		{
			DoAnimation (animate, () => SetImageURI (uri));
		}
	}
}

To use it, replace occurences of ImageView with FadeImageView. You can use it in Android XML layouts or in code. To activate the animation, simply use the overload accepting a boolean.