Correct the ImageView's adjustViewBounds behaviour on API Level 17 and below
In your application, you have a requirement like “I want to scale up an ImageView proportionally to fit its parent. How can I do that?“
[![android_imageview_ad
In this case, I was use ImageView and set its width attribute is match_parent
and set its adjustViewBounds
is true
, like code below.
<ImageView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@mipmap/ic_launcher" />
Here is the result:
[![android_imageview_ad
Everything looks fine?
Actually not. When I run application in Android device version API 17 or below, I don’t have expect result.
[![android_imageview_ad
This issue noted in the office document.
Note: If the application targets API level 17 or lower, adjustViewBounds
will allow the drawable to shrink the view bounds, but not grow to fill available measured space in all cases. This is for compatibility with legacy MeasureSpec
and RelativeLayout
behavior.
It mean: In targets level 17 or lower, ImageView‘s max with and max height defined in android:src
. Then the result that we received is not expect.
If your application support for targets level 17 or lower, you must resolve this. Now, in this article I will show you how to make a custom ImageView that can use adjustViewBounds
attribute in targets 17 or below.
package net.awpspace.adjustviewbounddemo;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView; /** * Created by Administrator on 22-Aug-15. */
public class AdjustableImageView extends ImageView {
boolean mAdjustViewBounds;
public AdjustableImageView(Context context) {
super(context);
}
public AdjustableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AdjustableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override public void setAdjustViewBounds(boolean adjustViewBounds) {
mAdjustViewBounds = adjustViewBounds;
super.setAdjustViewBounds(adjustViewBounds);
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable mDrawable = getDrawable();
if (mDrawable == null) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
return;
}
if (mAdjustViewBounds) {
int mDrawableWidth = mDrawable.getIntrinsicWidth();
int mDrawableHeight = mDrawable.getIntrinsicHeight();
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY && widthMode != MeasureSpec.EXACTLY) {
// Fixed Height & Adjustable Width
int height = heightSize;
int width = height * mDrawableWidth / mDrawableHeight;
if (isInScrollingContainer()) setMeasuredDimension(width, height);
else setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
} else if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
// Fixed Width & Adjustable Height
int width = widthSize;
int height = width * mDrawableHeight / mDrawableWidth;
if (isInScrollingContainer()) setMeasuredDimension(width, height);
else setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
private boolean isInScrollingContainer() {
ViewParent p = getParent();
while (p != null && p instanceof ViewGroup) {
if (((ViewGroup) p).shouldDelayChildPressedState()) {
return true;
}
p = p.getParent();
}
return false;
}
}
The issue resolved when I use AdjustableImageView
, here is the result:
[![android_imageview_ad