如何在Android中为ImageView设置最小和最大大小

16

我希望为一个ImageView指定最小宽度/高度和最大宽度/高度,图像应按比例缩放以适应指定的大小。

尝试以下代码:

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="100dp"
    android:maxWidth="200dp"
    android:minHeight="100dp"
    android:maxHeight="200dp"
    android:src="@drawable/ic_launcher" />

最小宽度和高度表现正常,但最大宽度和高度被忽略。

如果我设置 android:adjustViewBounds="true":

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter"
    android:minWidth="100dp"
    android:maxWidth="200dp"
    android:minHeight="100dp"
    android:maxHeight="200dp"
    android:src="@drawable/ic_launcher" />

比如说,最大宽度和高度的限制可以正常起作用,但是最小宽度和高度却被忽略了。

有没有办法两者都能起作用呢?

3个回答

11

最终,我创建了一个扩展ImageView并且覆盖onMeasure()方法的自定义视图:

public class ResizingImageView extends ImageView {

    private int mMaxWidth;
    private int mMaxHeight;

    public ResizingImageView(Context context) {
        super(context);
    }

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

    public ResizingImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setMaxWidth(int maxWidth) {
        super.setMaxWidth(maxWidth);
        mMaxWidth = maxWidth;
    }

    @Override
    public void setMaxHeight(int maxHeight) {
        super.setMaxHeight(maxHeight);
        mMaxHeight = maxHeight;
    }

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

        Drawable drawable = getDrawable();
        if (drawable != null) {

            int wMode = MeasureSpec.getMode(widthMeasureSpec);
            int hMode = MeasureSpec.getMode(heightMeasureSpec);
            if (wMode == MeasureSpec.EXACTLY || hMode == MeasureSpec.EXACTLY) {
                return;
            }

            // Calculate the most appropriate size for the view. Take into
            // account minWidth, minHeight, maxWith, maxHeigh and allowed size
            // for the view.

            int maxWidth = wMode == MeasureSpec.AT_MOST
                    ? Math.min(MeasureSpec.getSize(widthMeasureSpec), mMaxWidth)
                    : mMaxWidth;
            int maxHeight = hMode == MeasureSpec.AT_MOST
                    ? Math.min(MeasureSpec.getSize(heightMeasureSpec), mMaxHeight)
                    : mMaxHeight;

            int dWidth = Helpers.dipsToPixels(drawable.getIntrinsicWidth());
            int dHeight = Helpers.dipsToPixels(drawable.getIntrinsicHeight());
            float ratio = ((float) dWidth) / dHeight;

            int width = Math.min(Math.max(dWidth, getSuggestedMinimumWidth()), maxWidth);
            int height = (int) (width / ratio);

            height = Math.min(Math.max(height, getSuggestedMinimumHeight()), maxHeight);
            width = (int) (height * ratio);

            if (width > maxWidth) {
                width = maxWidth;
                height = (int) (width / ratio);
            }

            setMeasuredDimension(width, height);
        }
    }
}

现在可以像这样使用此视图:

<my.package.ResizingImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minWidth="100dp"
    android:maxWidth="200dp"
    android:minHeight="100dp"
    android:maxHeight="200dp"
    android:src="@drawable/ic_launcher" />

这个方法可以达到我想要的效果,但是难道没有更简单的解决方案吗?


12
你说得对。我已经厌倦了在Android上不能做简单的事情。 - tasomaniac

5
这在仅有XML的情况下曾经几乎不可能,但现在通过ConstraintLayout,它变得相当简单。
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintWidth_min="100dp"
        app:layout_constraintWidth_max="200dp"
        app:layout_constraintHeight_min="100dp"
        app:layout_constraintHeight_max="200dp"
        app:layout_constrainedWidth="true"
        app:layout_constrainedHeight="true"
        android:scaleType="centerCrop" />
</androidx.constraintlayout.widget.ConstraintLayout>

你可以使用 fitXY 或者 centerCropscaleType;其他选项将不会强制图片适应 ImageView

0
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:minWidth="150dp"
            android:minHeight="150dp"
            >

            <RelativeLayout
                android:id="@+id/imageLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/white"
                android:layout_gravity="center_vertical"
                >

                <ImageView
                    android:id="@+id/image"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:adjustViewBounds="true"
                    android:src="@drawable/trump"

                    />

                <ProgressBar
                    android:id="@+id/progressBar"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:visibility="gone" />
            </RelativeLayout>
        </LinearLayout>

请给容器布局设置最小高度和宽度,并在ImageView中使用adjustViewBounds。这样,您的任务将可以简单地完成。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接