package com.dwdesign.tweetings.view; import com.dwdesign.tweetings.R; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.NinePatchDrawable; import android.graphics.drawable.TransitionDrawable; import android.util.AttributeSet; public class StatusListPreviewImageView extends RoundCorneredImageView { public StatusListPreviewImageView(final Context context) { this(context, null); } public StatusListPreviewImageView(final Context context, final AttributeSet attrs) { this(context, attrs, 0); } public StatusListPreviewImageView(final Context context, final AttributeSet attrs, final int defStyle) { super(context, attrs, defStyle); setScaleType(ScaleType.MATRIX); } @Override protected boolean setFrame(final int frameLeft, final int frameTop, final int frameRight, final int frameBottom) { final float frameWidth = frameRight - frameLeft; final float frameHeight = frameBottom - frameTop; final Drawable drawable = getDrawable(); if (drawable == null) return super.setFrame(frameLeft, frameTop, frameRight, frameBottom); int translatey = 0; final Bitmap bitmap = getBitmap(drawable); if (bitmap != null) { setBackgroundDrawable(null); final int bw = bitmap.getWidth(); final int bh = bitmap.getHeight(); final float ratio = bh / bw; if (frameWidth * ratio > frameHeight) { final int stepw = limit(bw / 32, 1, bw); final int steph = limit(bh / 96, 1, bh); for (int x = 0, y = 0; x < bw && y < bh / 2; x += stepw, y += steph) { if (!isBorder(bitmap.getPixel(x, y))) { translatey = y; break; } } } } else { setBackgroundResource(R.drawable.image_preview_fallback_large); } final float originalImageWidth = drawable.getIntrinsicWidth(); final float originalImageHeight = drawable.getIntrinsicHeight(); float usedScaleFactor = 1; if (frameWidth > originalImageWidth || frameHeight > originalImageHeight) { // If frame is bigger than image => Crop it, keep aspect ratio and // position it at the bottom and center horizontally final float fitHorizontallyScaleFactor = frameWidth / originalImageWidth; final float fitVerticallyScaleFactor = frameHeight / originalImageHeight; usedScaleFactor = Math.max(fitHorizontallyScaleFactor, fitVerticallyScaleFactor); } final float newImageWidth = originalImageWidth * usedScaleFactor; final Matrix matrix = getImageMatrix(); // Replaces the old matrix completly matrix.setScale(usedScaleFactor, usedScaleFactor, 0, 0); matrix.postTranslate((frameWidth - newImageWidth) / 2, translatey > 0 ? -translatey * usedScaleFactor : 0); setImageMatrix(matrix); return super.setFrame(frameLeft, frameTop, frameRight, frameBottom); } private static boolean inRange(final int value, final int min, final int max, final int threshold) { return Math.abs(value - max) <= threshold || Math.abs(value - min) <= threshold; } private static boolean isBorder(final int color) { final int alpha = color >> 24 & 0xFF; final int red = color >> 16 & 0xFF; final int green = color >> 8 & 0xFF; final int blue = color & 0xFF; return inRange(alpha, 0x00, 0xFF, 8) && inRange(red, 0x00, 0xFF, 8) && inRange(green, 0x00, 0xFF, 8) && inRange(blue, 0x00, 0xFF, 8); } private static int limit(final int value, final int min, final int max) { if (value < min) return min; if (value > max) return max; return value; } static Bitmap getBitmap(final Drawable drawable) { if (drawable instanceof NinePatchDrawable) return null; if (drawable instanceof BitmapDrawable) return ((BitmapDrawable) drawable).getBitmap(); else if (drawable instanceof TransitionDrawable) { final int layer_count = ((TransitionDrawable) drawable).getNumberOfLayers(); for (int i = 0; i < layer_count; i++) { final Drawable layer = ((TransitionDrawable) drawable).getDrawable(i); if (layer instanceof BitmapDrawable) return ((BitmapDrawable) layer).getBitmap(); } } return null; } }