/** * galaxy inc. * meetup client for android */ package com.galaxy.meetup.client.android.ui.view; import WriteReviewOperation.MediaRef; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import com.galaxy.meetup.client.android.R; import com.galaxy.meetup.client.android.common.Recyclable; import com.galaxy.meetup.client.android.service.ImageResourceManager; import com.galaxy.meetup.client.android.service.Resource; import com.galaxy.meetup.client.android.service.ResourceConsumer; import com.galaxy.meetup.client.util.GifDrawable; import com.galaxy.meetup.client.util.GifImage; import com.galaxy.meetup.client.util.ImageUtils; import com.galaxy.meetup.client.util.ViewUtils; /** * * @author sihai * */ public class ImageResourceView extends View implements ResourceConsumer, Recyclable { private static Interpolator sDecelerateInterpolator; private static Bitmap sDefaultIcon; private static ImageResourceManager sImageManager; private static Bitmap sPanoramaIcon; private static final Paint sScalePaint; private static Bitmap sVideoIcon; private boolean mAnimationEnabled; private Bitmap mBitmap; private Matrix mBitmapMatrix; private boolean mClearCurrentContent; private int mCustomImageHeight; private int mCustomImageWidth; private boolean mDefaultIconEnabled; private int mDefaultIconX; private int mDefaultIconY; private Rect mDestinationRect; private RectF mDestinationRectF; private Drawable mDrawable; private boolean mFadeIn; private int mImageResourceFlags; private int mLastRequestedHeight; private int mLastRequestedWidth; private Matrix mMatrix; private MediaRef mMediaRef; private Drawable mOverlayDrawable; private int mPanoramaIconX; private int mPanoramaIconY; private boolean mPaused; private boolean mReleaseImageWhenPaused; private long mRequestTime; private Resource mResource; private Drawable mResourceBrokenDrawable; private Drawable mResourceLoadingDrawable; private boolean mResourceMissing; private Drawable mResourceMissingDrawable; private int mScaleMode; private Drawable mSelectorDrawable; private int mSizeCategory; private Rect mSourceRect; private RectF mSourceRectF; private int mVideoIconX; private int mVideoIconY; static { Paint paint = new Paint(); sScalePaint = paint; paint.setFilterBitmap(true); } public ImageResourceView(Context context) { super(context); mSizeCategory = 1; mScaleMode = 1; mSourceRect = new Rect(); mDestinationRect = new Rect(); mDestinationRectF = new RectF(); mSourceRectF = new RectF(); mMatrix = new Matrix(); mAnimationEnabled = true; init(context, null); } public ImageResourceView(Context context, AttributeSet attributeset) { super(context, attributeset); mSizeCategory = 1; mScaleMode = 1; mSourceRect = new Rect(); mDestinationRect = new Rect(); mDestinationRectF = new RectF(); mSourceRectF = new RectF(); mMatrix = new Matrix(); mAnimationEnabled = true; init(context, attributeset); } public ImageResourceView(Context context, AttributeSet attributeset, int i) { super(context, attributeset, i); mSizeCategory = 1; mScaleMode = 1; mSourceRect = new Rect(); mDestinationRect = new Rect(); mDestinationRectF = new RectF(); mSourceRectF = new RectF(); mMatrix = new Matrix(); mAnimationEnabled = true; init(context, attributeset); } private void init(Context context, AttributeSet attributeset) { if(sImageManager == null) { sImageManager = ImageResourceManager.getInstance(context); sVideoIcon = ImageUtils.decodeResource(context.getResources(), R.drawable.ic_video_play); sPanoramaIcon = ImageUtils.decodeResource(context.getResources(), R.drawable.overlay_lightcycle); sDefaultIcon = ImageUtils.decodeResource(context.getResources(), R.drawable.ic_missing_photo); } mSelectorDrawable = context.getResources().getDrawable(R.drawable.stream_list_selector); mSelectorDrawable.setCallback(this); if(attributeset == null) { return; } String s = attributeset.getAttributeValue(null, "size"); if(s != null) if("custom".equals(s)) mSizeCategory = 0; else if("thumbnail".equals(s)) mSizeCategory = 2; else if("large".equals(s)) mSizeCategory = 3; else if("portrait".equals(s)) mSizeCategory = 4; else if("landscape".equals(s)) mSizeCategory = 5; else if("full".equals(s)) mSizeCategory = 1; else throw new IllegalArgumentException((new StringBuilder("Invalid size category: ")).append(s).toString()); String s1 = attributeset.getAttributeValue(null, "scale"); if(s1 == null) { return; } if("zoom".equals(s1)) { mScaleMode = 1; return; } if("fit".equals(s1)) { mScaleMode = 0; return; } throw new IllegalArgumentException((new StringBuilder("Invalid scale mode: ")).append(s1).toString()); } private void clearDrawable() { if(mDrawable != null) mDrawable.setCallback(null); if(mDrawable instanceof Recyclable) ((Recyclable)mDrawable).onRecycle(); mDrawable = null; } private void computeRects(int i, int j) { int k = getPaddingTop(); int l = getPaddingRight(); int i1 = getPaddingBottom(); int j1 = getPaddingLeft(); int k1 = getWidth() - j1 - l; int l1 = getHeight() - k - i1; float f = (float)i / (float)j; float f1 = (float)k1 / (float)l1; if(0 == mScaleMode) { mSourceRect.set(0, 0, i, j); if(f > f1) { int i3 = (l1 - (int)((float)k1 / f)) / 2; mDestinationRect.set(j1, k + i3, j1 + k1, (k + l1) - i3); } else { int l2 = (k1 - (int)(f * (float)l1)) / 2; mDestinationRect.set(j1 + l2, k, (j1 + k1) - l2, k + l1); } } else if(1 == mScaleMode) { if(f > f1) { int k2 = (i - (int)(f1 * (float)j)) / 2; mSourceRect.set(k2, 0, i - k2, j); } else { int i2 = (int)((float)i / f1); int j2 = Math.max((int)(0.4F * (float)j) - i2 / 2, 0); mSourceRect.set(0, j2, i, j2 + i2); } mDestinationRect.set(j1, k, j1 + k1, k + l1); } else if(2 == mScaleMode) { mSourceRect.set(0, 0, i, j); mDestinationRect.set(0, 0, k1, l1); } else { mSourceRectF.set(mSourceRect); mDestinationRectF.set(mDestinationRect); mMatrix.setRectToRect(mSourceRectF, mDestinationRectF, android.graphics.Matrix.ScaleToFit.FILL); } } private void drawResourceStatus(Canvas canvas, Drawable drawable) { if(drawable != null) { drawable.setBounds(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); drawable.draw(canvas); } } private Drawable getDrawable(int i) { Drawable drawable; if(i == 0) drawable = null; else drawable = getResources().getDrawable(i); return drawable; } private boolean hasDrawable() { boolean flag; if(hasImage() && (mResource.getResource() instanceof GifImage)) flag = true; else flag = false; return flag; } public final void bindResources() { if(ViewUtils.isViewAttached(this) && !mPaused) { mRequestTime = System.currentTimeMillis(); if(mMediaRef != null) { if(mSizeCategory == 0) { int i; int j; if(mCustomImageWidth != 0 || mCustomImageHeight != 0) { i = mCustomImageWidth; j = mCustomImageHeight; } else { i = getWidth(); j = getHeight(); } if((i != 0 || j != 0) && (mLastRequestedHeight != j || mLastRequestedWidth != i)) { mResource = sImageManager.getMedia(mMediaRef, i, j, mImageResourceFlags, this); mLastRequestedWidth = i; mLastRequestedHeight = j; } } else { mResource = sImageManager.getMedia(mMediaRef, mSizeCategory, mImageResourceFlags, this); } } else { mBitmap = null; clearDrawable(); } } } public void draw(Canvas canvas) { super.draw(canvas); if(!isPressed() && !isFocused()) { if(isSelected()) { mSelectorDrawable.setBounds(getPaddingLeft(), getPaddingTop(), getWidth() - getPaddingRight(), getHeight() - getPaddingBottom()); mSelectorDrawable.draw(canvas); } } else { mSelectorDrawable.setBounds(0, 0, getWidth(), getHeight()); mSelectorDrawable.draw(canvas); } } protected void drawableStateChanged() { mSelectorDrawable.setState(getDrawableState()); invalidate(); super.drawableStateChanged(); } protected final Bitmap getBitmap() { Bitmap bitmap; if(hasBitmap()) bitmap = (Bitmap)mResource.getResource(); else bitmap = mBitmap; return bitmap; } public final MediaRef getMediaRef() { return mMediaRef; } protected final boolean hasBitmap() { boolean flag; if(hasImage() && (mResource.getResource() instanceof Bitmap)) flag = true; else flag = false; return flag; } public final boolean hasImage() { boolean flag = true; if(mResource == null || mResource.getStatus() != 1) flag = false; return flag; } public void invalidateDrawable(Drawable drawable) { if(drawable == mDrawable) invalidate(); else super.invalidateDrawable(drawable); } public void jumpDrawablesToCurrentState() { super.jumpDrawablesToCurrentState(); if(mDrawable != null) mDrawable.jumpToCurrentState(); } protected void onAttachedToWindow() { super.onAttachedToWindow(); mPaused = false; bindResources(); } protected void onDetachedFromWindow() { super.onDetachedFromWindow(); onUnbindResources(); } protected void onDraw(Canvas canvas) { super.onDraw(canvas); boolean flag = hasBitmap(); if (!flag && !hasDrawable()) { if (mDefaultIconEnabled) { canvas.drawBitmap(sDefaultIcon, mDefaultIconX, mDefaultIconY, null); } else { if (mResource != null) switch (mResource.getStatus()) { case 0: // '\0' case 2: // '\002' case 3: // '\003' drawResourceStatus(canvas, mResourceLoadingDrawable); break; case 4: // '\004' drawResourceStatus(canvas, mResourceMissingDrawable); break; case 5: // '\005' case 6: // '\006' case 7: // '\007' drawResourceStatus(canvas, mResourceBrokenDrawable); break; } else if (mResourceMissing) drawResourceStatus(canvas, mResourceMissingDrawable); else drawResourceStatus(canvas, mResourceLoadingDrawable); } } else { boolean flag1; if (flag) { Bitmap bitmap = getBitmap(); if (bitmap != null && !bitmap.isRecycled()) { if (mSourceRect.isEmpty()) computeRects(bitmap.getWidth(), bitmap.getHeight()); if (mScaleMode == 2 && mBitmapMatrix != null) canvas.drawBitmap(bitmap, mBitmapMatrix, sScalePaint); else canvas.drawBitmap(bitmap, mSourceRect, mDestinationRect, sScalePaint); } } else { if (mDrawable == null && hasDrawable()) { mSourceRect.setEmpty(); mDrawable = new GifDrawable( (GifImage) mResource.getResource()); ((GifDrawable) mDrawable) .setAnimationEnabled(mAnimationEnabled); mDrawable.setCallback(this); } Drawable drawable = mDrawable; if (drawable != null) if ((drawable instanceof GifDrawable) && !((GifDrawable) drawable).isValid()) { if (mDefaultIconEnabled) canvas.drawBitmap(sDefaultIcon, mDefaultIconX, mDefaultIconY, null); else drawResourceStatus(canvas, mResourceBrokenDrawable); } else { int i = drawable.getIntrinsicWidth(); int j = drawable.getIntrinsicHeight(); if (mSourceRect.isEmpty()) computeRects(i, j); canvas.save(); drawable.setBounds(0, 0, i, j); canvas.concat(mMatrix); drawable.draw(canvas); canvas.restore(); } } if (mMediaRef != null && MediaRef.MediaType.VIDEO == mMediaRef.getType()) flag1 = true; else flag1 = false; if (flag1) { canvas.drawBitmap(sVideoIcon, mVideoIconX, mVideoIconY, null); } else { boolean flag2; if (mMediaRef != null && MediaRef.MediaType.PANORAMA == mMediaRef.getType()) flag2 = true; else if (mResource != null && mResource.getResourceType() == 2) flag2 = true; else flag2 = false; if (flag2) canvas.drawBitmap(sPanoramaIcon, mPanoramaIconX, mPanoramaIconY, null); } } if (mOverlayDrawable != null) { mOverlayDrawable.setBounds(0, 0, getWidth(), getHeight()); mOverlayDrawable.draw(canvas); } } protected void onLayout(boolean flag, int i, int j, int k, int l) { super.onLayout(flag, i, j, k, l); int i1 = k - i; int j1 = l - j; mVideoIconX = (i1 - sVideoIcon.getWidth()) / 2; mVideoIconY = (j1 - sVideoIcon.getHeight()) / 2; mPanoramaIconX = (i1 - sPanoramaIcon.getWidth()) / 2; mPanoramaIconY = (j1 - sPanoramaIcon.getHeight()) / 2; mDefaultIconX = (i1 - sDefaultIcon.getWidth()) / 2; mDefaultIconY = (j1 - sDefaultIcon.getHeight()) / 2; if(flag && mSizeCategory == 0) { onUnbindResources(); bindResources(); } } public void onRecycle() { onUnbindResources(); setMediaRef(null); } public final void onResourceStatusChange(Resource resource) { if(1 == resource.getStatus()) { if(System.currentTimeMillis() - mRequestTime > 100L && mFadeIn && android.os.Build.VERSION.SDK_INT >= 12) { if(sDecelerateInterpolator == null) sDecelerateInterpolator = new DecelerateInterpolator(); setAlpha(0.01F); animate().alpha(1.0F).setDuration(500L).setInterpolator(sDecelerateInterpolator); } } invalidate(); } public final void onResume() { if(mReleaseImageWhenPaused) { mPaused = false; bindResources(); } } public final void onStop() { if(mReleaseImageWhenPaused) { mPaused = true; onUnbindResources(); } } protected void onUnbindResources() { if(mResource != null) { mResource.unregister(this); mResource = null; } if(!mClearCurrentContent) mBitmap = getBitmap(); clearDrawable(); mOverlayDrawable = null; mSourceRect.setEmpty(); mLastRequestedWidth = 0; mLastRequestedHeight = 0; } public void setCustomImageSize(int i, int j) { mCustomImageWidth = i; mCustomImageHeight = j; } public void setDefaultIconEnabled(boolean flag) { if(flag != mDefaultIconEnabled) { mDefaultIconEnabled = flag; invalidate(); } } public void setFadeIn(boolean flag) { mFadeIn = flag; } public void setImageMatrix(Matrix matrix) { mBitmapMatrix = matrix; } public void setImageResourceFlags(int i) { mImageResourceFlags = i; } public void setMediaRef(MediaRef mediaref) { setMediaRef(mediaref, true); } public void setMediaRef(MediaRef mediaref, boolean flag) { if(mMediaRef == null || !mMediaRef.equals(mediaref)) { mClearCurrentContent = flag; onUnbindResources(); mMediaRef = mediaref; if(mMediaRef != null) mResourceMissing = false; bindResources(); invalidate(); } } public void setOverlay(Drawable drawable) { if(mOverlayDrawable != drawable) { mOverlayDrawable = drawable; invalidate(); } } public void setReleaseImageWhenPaused(boolean flag) { mReleaseImageWhenPaused = flag; } public void setResourceBrokenDrawable(int i) { mResourceBrokenDrawable = getDrawable(i); } public void setResourceBrokenDrawable(Drawable drawable) { mResourceBrokenDrawable = drawable; } public void setResourceLoadingDrawable(int i) { mResourceLoadingDrawable = getDrawable(i); } public void setResourceLoadingDrawable(Drawable drawable) { mResourceLoadingDrawable = drawable; } public void setResourceMissing(boolean flag) { mResourceMissing = flag; } public void setResourceMissingDrawable(int i) { mResourceMissingDrawable = getDrawable(i); } public void setResourceMissingDrawable(Drawable drawable) { mResourceMissingDrawable = drawable; } public void setScaleMode(int i) { if(i != mScaleMode) { mScaleMode = i; mSourceRect.setEmpty(); invalidate(); } } public void setSelected(boolean flag) { if(flag != isSelected()) { super.setSelected(flag); if(mSelectorDrawable != null) invalidate(); } } public void setSelector(Drawable drawable) { mSelectorDrawable = drawable; if(mSelectorDrawable != null) mSelectorDrawable.setCallback(this); } public void setSizeCategory(int i) { mSizeCategory = i; } public final void unbindResources() { onUnbindResources(); } protected boolean verifyDrawable(Drawable drawable) { boolean flag; if(drawable == mSelectorDrawable || drawable == mDrawable) flag = true; else flag = super.verifyDrawable(drawable); return flag; } }