package edu.mit.mitmobile2; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.os.Handler; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.ImageView.ScaleType; public class RemoteImageView extends FrameLayout { private ImageView mBusyBox; private ImageView mErrorImage; protected ImageView mContentView; private List<String> mUrls; private ImageDiskCache mDiskCache; private BitmapFactory.Options mBitmapDecodeOptions; private Integer mScreenDensity; public RemoteImageView(Context context, AttributeSet attrs) { super(context, attrs); inflateImageLayout(context); int scaleTypeInt= attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "scaleType", -1); mBusyBox = (ImageView) findViewById(R.id.remoteImageViewLoader); mErrorImage = (ImageView) findViewById(R.id.remoteImageViewError); mContentView = (ImageView) findViewById(R.id.remoteImageViewContent); if(scaleTypeInt >= 0) { setScaleType(ScaleType.values()[scaleTypeInt]); } mDiskCache = new ImageDiskCache(context); } public void inflateImageLayout(Context context) { LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflator.inflate(R.layout.remote_imageview, this); } public void updateImage(Bitmap image) { mContentView.setImageBitmap(image); } public void setScaleType(ScaleType scaleType) { mContentView.setScaleType(scaleType); } public synchronized void setBitmapDecodeOptions(BitmapFactory.Options decodeOptions) { mBitmapDecodeOptions = decodeOptions; } public void refresh() { if(mErrorImage.getVisibility() == VISIBLE) { setURLs(mUrls, true); } } public void setURL(String url) { ArrayList<String> urls = new ArrayList<String>(); urls.add(url); setURLs(urls, false); } public void setURLs(List<String> urls) { setURLs(urls, false); } public void setScreenDensity(Integer density) { mScreenDensity = density; } private static boolean compareURLs(List<String> urls1, List<String> urls2) { if (urls1 == null || urls2 == null) { // only way to be equal is both objects are null return urls1 == urls2; } if (urls1.size() == urls2.size()) { for (int i = 0; i < urls1.size(); i++) { if (!urls1.get(i).equals(urls2.get(i))) { return false; } } return true; } else { return false; } } private synchronized void setURLs(final List<String> urls, boolean forceRefresh) { if(urls == null) { mContentView.setImageDrawable(null); mUrls = null; return; } if (!forceRefresh) { if (compareURLs(mUrls, urls)) { // nothing to update return; } } // clear the old contents first mContentView.setImageDrawable(null); mUrls = urls; mErrorImage.setVisibility(GONE); mBusyBox.setVisibility(VISIBLE); LoadingUIHelper.startLoadingImage(new Handler(), mBusyBox); final Handler uiHandler = new Handler(); Thread loadImageThread = new Thread() { @Override public void run() { int width = -1; int height = -1; Bitmap image = null; Canvas canvas = null; for (String url : urls) { final Bitmap layerImage; final byte[] imageBytes = mDiskCache.getImageBytes(url); if(imageBytes != null) { layerImage = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, mBitmapDecodeOptions); } else { layerImage = null; Log.d("RemoteImageView", "Failed to decode image: " + url); break; } if (urls.size() > 1) { if (image == null) { // dont worry about width = layerImage.getWidth(); height = layerImage.getHeight(); image = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); canvas = new Canvas(image); canvas.drawBitmap(layerImage, 0, 0, new Paint()); } else { if (width != layerImage.getWidth() || height != layerImage.getHeight()) { image = null; Log.d("RemoteImageView", "Image Size for " + url + " does not match the size of base image " + urls.get(0)); } else { canvas.drawBitmap(layerImage, 0, 0, new Paint()); } } } else { // for a single image no need to do any fancy canvas // drawing image = layerImage; } } if (image != null && mScreenDensity != null) { image.setDensity(mScreenDensity); } synchronized (RemoteImageView.this) { if(compareURLs(mUrls, urls)) { // check to make sure URL has not changed final Bitmap finalImage = image; uiHandler.post(new Runnable() { @Override public void run() { if(compareURLs(mUrls, urls)) { // check to make sure URL has not changed if(finalImage != null) { mBusyBox.setVisibility(GONE); mErrorImage.setVisibility(GONE); updateImage(finalImage); mContentView.setVisibility(VISIBLE); } else { mBusyBox.setVisibility(GONE); mContentView.setVisibility(GONE); mErrorImage.setVisibility(VISIBLE); } } } }); } } } }; loadImageThread.setPriority(Thread.MIN_PRIORITY); loadImageThread.start(); } }