public
Last active

ImageView that respects an aspect ratio applied to a specific measurement.

  • Download Gist
AspectRatioImageView.java
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
// Copyright 2012 Square, Inc.
package com.squareup.widgets;
 
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;
 
/** Maintains an aspect ratio based on either width or height. Disabled by default. */
public class AspectRatioImageView extends ImageView {
// NOTE: These must be kept in sync with the AspectRatioImageView attributes in attrs.xml.
public static final int MEASUREMENT_WIDTH = 0;
public static final int MEASUREMENT_HEIGHT = 1;
 
private static final float DEFAULT_ASPECT_RATIO = 1f;
private static final boolean DEFAULT_ASPECT_RATIO_ENABLED = false;
private static final int DEFAULT_DOMINANT_MEASUREMENT = MEASUREMENT_WIDTH;
 
private float aspectRatio;
private boolean aspectRatioEnabled;
private int dominantMeasurement;
 
public AspectRatioImageView(Context context) {
this(context, null);
}
 
public AspectRatioImageView(Context context, AttributeSet attrs) {
super(context, attrs);
 
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AspectRatioImageView);
aspectRatio = a.getFloat(R.styleable.AspectRatioImageView_aspectRatio, DEFAULT_ASPECT_RATIO);
aspectRatioEnabled = a.getBoolean(R.styleable.AspectRatioImageView_aspectRatioEnabled,
DEFAULT_ASPECT_RATIO_ENABLED);
dominantMeasurement = a.getInt(R.styleable.AspectRatioImageView_dominantMeasurement,
DEFAULT_DOMINANT_MEASUREMENT);
a.recycle();
}
 
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!aspectRatioEnabled) return;
 
int newWidth;
int newHeight;
switch (dominantMeasurement) {
case MEASUREMENT_WIDTH:
newWidth = getMeasuredWidth();
newHeight = (int) (newWidth * aspectRatio);
break;
 
case MEASUREMENT_HEIGHT:
newHeight = getMeasuredHeight();
newWidth = (int) (newHeight * aspectRatio);
break;
 
default:
throw new IllegalStateException("Unknown measurement with ID " + dominantMeasurement);
}
 
setMeasuredDimension(newWidth, newHeight);
}
 
/** Get the aspect ratio for this image view. */
public float getAspectRatio() {
return aspectRatio;
}
 
/** Set the aspect ratio for this image view. This will update the view instantly. */
public void setAspectRatio(float aspectRatio) {
this.aspectRatio = aspectRatio;
if (aspectRatioEnabled) {
requestLayout();
}
}
 
/** Get whether or not forcing the aspect ratio is enabled. */
public boolean getAspectRatioEnabled() {
return aspectRatioEnabled;
}
 
/** set whether or not forcing the aspect ratio is enabled. This will re-layout the view. */
public void setAspectRatioEnabled(boolean aspectRatioEnabled) {
this.aspectRatioEnabled = aspectRatioEnabled;
requestLayout();
}
 
/** Get the dominant measurement for the aspect ratio. */
public int getDominantMeasurement() {
return dominantMeasurement;
}
 
/**
* Set the dominant measurement for the aspect ratio.
*
* @see #MEASUREMENT_WIDTH
* @see #MEASUREMENT_HEIGHT
*/
public void setDominantMeasurement(int dominantMeasurement) {
if (dominantMeasurement != MEASUREMENT_HEIGHT && dominantMeasurement != MEASUREMENT_WIDTH) {
throw new IllegalArgumentException("Invalid measurement type.");
}
this.dominantMeasurement = dominantMeasurement;
requestLayout();
}
}
attrs.xml
XML
1 2 3 4 5 6 7 8
<declare-styleable name="AspectRatioImageView">
<attr name="aspectRatio" format="float" />
<attr name="aspectRatioEnabled" format="boolean" />
<attr name="dominantMeasurement">
<enum name="width" value="0"/>
<enum name="height" value="1"/>
</attr>
</declare-styleable>

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.