package com.blundell.tut; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import roboguice.RoboGuice; import roboguice.util.Ln; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Handler.Callback; import android.os.Message; import android.util.AttributeSet; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; /** * Free for anyone to use, just say thanks and share :-) * @author Blundell * */ public class LoaderImageView extends LinearLayout{ private static final int COMPLETE = 0; private static final int FAILED = 1; private static final int SPIN = 2; private Context mContext; private Drawable mDrawable; private ProgressBar mSpinner; private ImageView mImage; private Integer errorResource; /** * This is used when creating the view in XML * To have an image load in XML use the tag 'image="http://developer.android.com/images/dialog_buttons.png"' * To specify the image to display in case of failure, use 'error="R.drawable.something"' * Replacing the url with your desired image * Once you have instantiated the XML view you can call * setImageDrawable(url) to change the image * @param context * @param attrSet */ public LoaderImageView(final Context context, final AttributeSet attrSet) { super(context, attrSet); RoboGuice.getInjector(context).injectMembers(this); final String url = attrSet.getAttributeValue(null, "image"); errorResource = attrSet.getAttributeResourceValue(null, "error", 0); if(errorResource == 0) errorResource = null; if(url != null){ instantiate(context, url); } else { instantiate(context, null); } } /** * This is used when creating the view programatically * Once you have instantiated the view you can call * setImageDrawable(url) to change the image * @param context the Activity context * @param imageUrl the Image URL you wish to load */ public LoaderImageView(final Context context, final String imageUrl) { super(context); instantiate(context, imageUrl); } /** * First time loading of the LoaderImageView * Sets up the LayoutParams of the view, you can change these to * get the required effects you want */ private void instantiate(final Context context, final String imageUrl) { mContext = context; mImage = new ImageView(mContext); mImage.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); mSpinner = new ProgressBar(mContext); mSpinner.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); mSpinner.setIndeterminate(true); addView(mSpinner); addView(mImage); if(imageUrl == null){ spin(); }else{ setImageDrawable(imageUrl); } } /** * Show the spinner */ public void spin(){ imageLoadedHandler.sendEmptyMessage(SPIN); } /** * Set's the view's drawable, this uses the Internet to retrieve the image * don't forget to add the correct permissions to your manifest * @param imageUrl the url of the image you wish to load */ public void setImageDrawable(final String imageUrl) { mDrawable = null; mSpinner.setVisibility(View.VISIBLE); mImage.setVisibility(View.GONE); new Thread(){ public void run() { try { if(imageUrl==null){ imageLoadedHandler.sendEmptyMessage(FAILED); }else{ mDrawable = getDrawableFromUrl(imageUrl); imageLoadedHandler.sendEmptyMessage(COMPLETE); } } catch (MalformedURLException e) { imageLoadedHandler.sendEmptyMessage(FAILED); } catch (IOException e) { imageLoadedHandler.sendEmptyMessage(FAILED); } }; }.start(); } public void setImageResource(int resId){ mDrawable = getResources().getDrawable(resId); imageLoadedHandler.sendEmptyMessage(COMPLETE); } public void setErrorResource(int resId){ this.errorResource = resId; } /** * Callback that is received once the image has been downloaded */ private final Handler imageLoadedHandler = new Handler(new Callback() { public boolean handleMessage(Message msg) { Ln.v("Message is: %s", msg.what); switch (msg.what) { case COMPLETE: mImage.setImageDrawable(mDrawable); mImage.setVisibility(View.VISIBLE); mSpinner.setVisibility(View.GONE); break; case FAILED: if(errorResource == null){ mImage.setVisibility(View.GONE); }else{ mImage.setImageResource(errorResource); mImage.setVisibility(View.VISIBLE); } mSpinner.setVisibility(View.GONE); break; case SPIN: mImage.setVisibility(View.GONE); mSpinner.setVisibility(View.VISIBLE); break; } //the image could be of any dimensions. Set the dimensions of the image to the same dimensions as the LoaderImageView so the LoaderImageView doesn't suddenly drastically grow/shrink when the image loads. mImage.setLayoutParams(new LayoutParams(getMeasuredWidth(), getMeasuredHeight())); return true; } }); /** * Pass in an image url to get a drawable object * @return a drawable object * @throws IOException * @throws MalformedURLException */ private Drawable getDrawableFromUrl(final String url) throws IOException, MalformedURLException { final InputStream inputStream = new URL(url).openStream(); try{ return Drawable.createFromStream(inputStream, "name"); }finally{ inputStream.close(); } } }