package com.stackoverflow.android.widget;
import java.lang.reflect.Field;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
import edu.mit.mobile.android.flipr.R;
/**
* Preserves the aspect ratio of an image while allowing it to scale up.
*
* To use, set the width/height to 0dip of the side that you wish to resize. It will then be
* adjusted based on the aspect ratio of the image.
*
* {@link http
* ://stackoverflow.com/questions/2991110/android-how-to-stretch-an-image-to-the-screen-width
* -while-maintaining-aspect-ra/2999707}
*
*
*/
public class AspectRatioImageView extends ImageView {
private static final String TAG = AspectRatioImageView.class.getSimpleName();
int mMaxWidth = Integer.MAX_VALUE;
int mMaxHeight = Integer.MAX_VALUE;
private int mStretch;
private static final int STRETCH_UNDEFINED = -1;
private static final int STRETCH_HORIZONTAL = 0;
private static final int STRETCH_VERTICAL = 1;
public AspectRatioImageView(Context context) {
super(context);
init(context, null);
}
public AspectRatioImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public AspectRatioImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
// http://stackoverflow.com/questions/8311081/how-to-get-maxwidth-and-maxheight-parameters-of-imageview
// haaaaack
try {
final Field maxWidthField = ImageView.class.getDeclaredField("mMaxWidth");
final Field maxHeightField = ImageView.class.getDeclaredField("mMaxHeight");
maxWidthField.setAccessible(true);
maxHeightField.setAccessible(true);
mMaxWidth = (Integer) maxWidthField.get(this);
mMaxHeight = (Integer) maxHeightField.get(this);
} catch (final SecurityException e) {
// we don't care if we can't get it. We weren't really supposed to anyhow.
} catch (final NoSuchFieldException e) {
// we don't care if we can't get it. We weren't really supposed to anyhow.
} catch (final IllegalArgumentException e) {
// we don't care if we can't get it. We weren't really supposed to anyhow.
} catch (final IllegalAccessException e) {
// we don't care if we can't get it. We weren't really supposed to anyhow.
}
final TypedArray ta = context.obtainStyledAttributes(attrs,
R.styleable.AspectRatioImageView);
mStretch = ta.getInt(R.styleable.AspectRatioImageView_stretch, STRETCH_UNDEFINED);
setAdjustViewBounds(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final Drawable drawable = getDrawable();
boolean setMeasuredDimension = false;
if (drawable != null) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
if (MeasureSpec.EXACTLY == MeasureSpec.getMode(heightMeasureSpec)
&& (height == 0 || STRETCH_VERTICAL == mStretch)) {
final float diw = drawable.getIntrinsicWidth();
if (diw > 0) {
height = (int) Math.max(getSuggestedMinimumHeight(),
Math.min(width * (drawable.getIntrinsicHeight() / diw), mMaxHeight));
setMeasuredDimension(width, height);
setMeasuredDimension = true;
}
} else if (MeasureSpec.EXACTLY == MeasureSpec.getMode(widthMeasureSpec)
&& (width == 0 || STRETCH_HORIZONTAL == mStretch)) {
final float dih = drawable.getIntrinsicHeight();
if (dih > 0) {
width = (int) Math.max(getSuggestedMinimumWidth(),
Math.min(height * (drawable.getIntrinsicWidth() / dih), mMaxWidth));
setMeasuredDimension(width, height);
setMeasuredDimension = true;
}
}
}
if (!setMeasuredDimension) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}