/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.contacts.util; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.TransitionDrawable; import android.util.Log; import android.widget.ImageView; import com.android.contacts.ContactPhotoManager; import com.android.contacts.model.Contact; import java.util.Arrays; /** * Initialized with a target ImageView. When provided with a compressed image * (i.e. a byte[]), it appropriately updates the ImageView's Drawable. */ public class ImageViewDrawableSetter { private ImageView mTarget; private byte[] mCompressed; private Drawable mPreviousDrawable; private int mDurationInMillis = 0; private static final String TAG = "ImageViewDrawableSetter"; public ImageViewDrawableSetter() { } public ImageViewDrawableSetter(ImageView target) { mTarget = target; } public void setupContactPhoto(Contact contactData, ImageView photoView) { setTarget(photoView); setCompressedImage(contactData.getPhotoBinaryData()); } public void setTransitionDuration(int durationInMillis) { mDurationInMillis = durationInMillis; } public ImageView getTarget() { return mTarget; } /** * Re-initialize to use new target. As a result, the next time a new image * is set, it will immediately be applied to the target (there will be no * fade transition). */ protected void setTarget(ImageView target) { if (mTarget != target) { mTarget = target; mCompressed = null; mPreviousDrawable = null; } } protected byte[] getCompressedImage() { return mCompressed; } protected Bitmap setCompressedImage(byte[] compressed) { if (mPreviousDrawable == null) { // If we don't already have a drawable, skip the exit-early test // below; otherwise we might not end up setting the default image. } else if (mPreviousDrawable != null && Arrays.equals(mCompressed, compressed)) { // TODO: the worst case is when the arrays are equal but not // identical. This takes about 1ms (more with high-res photos). A // possible optimization is to sparsely sample chunks of the arrays // to compare. return previousBitmap(); } final Drawable newDrawable = (compressed == null) ? defaultDrawable() : decodedBitmapDrawable(compressed); // Remember this for next time, so that we can check if it changed. mCompressed = compressed; // If we don't have a new Drawable, something went wrong... bail out. if (newDrawable == null) return previousBitmap(); if (mPreviousDrawable == null || mDurationInMillis == 0) { // Set the new one immediately. mTarget.setImageDrawable(newDrawable); } else { // Set up a transition from the previous Drawable to the new one. final Drawable[] beforeAndAfter = new Drawable[2]; beforeAndAfter[0] = mPreviousDrawable; beforeAndAfter[1] = newDrawable; final TransitionDrawable transition = new TransitionDrawable(beforeAndAfter); mTarget.setImageDrawable(transition); transition.startTransition(mDurationInMillis); } // Remember this for next time, so that we can transition from it to the // new one. mPreviousDrawable = newDrawable; return previousBitmap(); } private Bitmap previousBitmap() { return (mPreviousDrawable == null) ? null : ((BitmapDrawable) mPreviousDrawable).getBitmap(); } /** * Obtain the default drawable for a contact when no photo is available. */ private Drawable defaultDrawable() { Resources resources = mTarget.getResources(); final int resId = ContactPhotoManager.getDefaultAvatarResId(true, false); try { return resources.getDrawable(resId); } catch (NotFoundException e) { Log.wtf(TAG, "Cannot load default avatar resource."); return null; } } private BitmapDrawable decodedBitmapDrawable(byte[] compressed) { Resources rsrc = mTarget.getResources(); Bitmap bitmap = BitmapFactory.decodeByteArray(compressed, 0, compressed.length); return new BitmapDrawable(rsrc, bitmap); } }