minWidth and minHeight has no effect on ImageView (Android)

1.5k Views Asked by At

For whatever reason, setting the minHeight and maxHeight has no effect on the image dimension inside an ImageView component. In some cases, I end up with a VERY SMALL image. I presume this is due to the fact that I have the width and height set to "wrap_content" and "adjustViewBounds" set to true.

If I set "adjustViewBounds" to false, the image does expand to whatever I specify for minWidth and/or minHeight. However, in this case the image becomes distorted because its width and height are not scaled in proportion. I would like to avoid this situation too.

I end up writing a big chunk of code (as follows) to overwrite the onMeasure() method of ImageView. Is this really necessary?

public class FlexibleImageView extends ImageView {

    private static final String LOG_TAG = "FlexibleImageView";

    public FlexibleImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        if(Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN) {
            boolean adjustViewBounds = getAdjustViewBounds();
            int minWidth = Math.max(getMinimumWidth(), getSuggestedMinimumWidth());
            int minHeight = Math.max(getMinimumHeight(), getSuggestedMinimumHeight());
            int maxWidth = getMaxWidth();
            int maxHeight = getMaxHeight();
            int widthSpec = getMeasuredWidth();
            int heightSpec = getMeasuredHeight();

            Drawable d = getDrawable();
            if (d != null && adjustViewBounds) {

                // Scale UP if the size is too small
                float scale, scaleW = 1.0f, scaleH = 1.0f;
                if (widthSpec < minWidth)
                    scaleW = (float) minWidth / (float) widthSpec;
                if (heightSpec < minHeight)
                    scaleH = (float) minHeight / (float) heightSpec;
                scale = (scaleW > scaleH) ? scaleW : scaleH;

                if (scale > 1.0) {

                    int targetW = (int) Math.ceil(widthSpec * scale);
                    int targetH = (int) Math.ceil(heightSpec * scale);

                    Log.d(LOG_TAG, "Measured dimension (" + widthSpec + "x" + heightSpec
                            + ") too small.  Resizing to " + targetW + "x" + targetH);

                    // Make sure targetW, targetH stays within the bounds of maxW, maxH
                    if(targetW > maxWidth) {
                        targetH = targetH * maxWidth / targetW;
                        targetW = maxWidth;

                        Log.d(LOG_TAG, "Capping width to " + maxWidth);
                    }
                    if(targetH > maxHeight) {
                        targetW = targetW * maxHeight / targetH;
                        targetH = maxHeight;

                        Log.d(LOG_TAG, "Capping height to " + maxHeight);
                    }
                    setMeasuredDimension(targetW, targetH);
                }
            }
        }
    }
}

And XML portion:

<cards.myb.ui.FlexibleImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/imageCard"
    android:contentDescription="@string/card_image"
    android:adjustViewBounds="true"
    android:minHeight="@dimen/card_editor_img_min_dimen"
    android:scaleType="fitXY"
    android:src="@drawable/fb_logo" />
0

There are 0 best solutions below