39

我希望 ImageView 的宽度由父级设置,高度应与纵横比。这样做的原因是接下来会显示一个我想放在 ImageView 下方的 TextView。

我可以使用正确显示图像

android:layout_width="fill_parent"
android:layout_height="fill_parent"

但是 ImageView 高度成为父高度,它比显示的拉伸图像大得多。一个想法是让父级垂直变小,但是……我还不知道拉伸后的图像大小。

以下不起作用,因为没有水平填充小图像。

android:layout_width="fill_parent"
android:layout_height="wrap_content"

乱搞

android:layout_height="wrap_content"

对于围绕它的 RelativeLayout 都无济于事。还尝试了 FrameLayout 和 LinearLayout 并失败了。

有任何想法吗?

4

4 回答 4

94

您必须将adjustViewBounds设置为 true。

imageView.setAdjustViewBounds(true);
于 2014-06-03T10:51:34.290 回答
39

如果您的实际图像尺寸等于或大于您的 ImageView 宽度和高度,则有两种情况,那么您可以使用 adjustViewBounds 属性,如果您的实际图像尺寸小于 ImageView 的宽度和高度,则根据您的使用 scaleType 属性在 ImageView 中显示图像要求。

1.实际图像大小等于或大于ImageView所需的宽度和高度。

<ImageView
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:src="@drawable/ic_launcher"/>

2.实际图片尺寸小于ImageView要求的宽高。

<ImageView
    android:layout_width="match_parent" 
    android:layout_height="wrap_content"
    android:scaleType="fitXY"
    android:src="@drawable/ic_launcher"/>
于 2013-10-30T03:45:58.610 回答
8

因此,我不止一次遇到过同样的问题,并且通过查看现有的 stackoverflow 答案已经意识到,没有任何答案可以完美地解释有关该问题的解决方案的真正困惑。所以你去:

API 17+

imageView.setAdjustViewBounds(true);

或(在 XML 中)

android:adjustViewBounds="true"

解决了这个问题,无论图像资源的实际大小如何,它都能正常工作,即它会将您的图像放大或缩小到您在布局中拥有的所需大小。

API 17 以下

API 17 以下android:adjustViewBounds="true"仅适用于缩小图像,而不是增长,即如果图像源的实际高度小于您在布局中尝试实现的尺寸,wrap_content将使用较小的高度而不是“放大”(放大) 你想要的图像。

因此对于 API 17 及更低版本,您别无选择,只能使用自定义 ImageView 来实现此行为。您可以自己编写自定义 ImageView 或使用已经完成该工作的库。

使用库

可能有不止一个库可以解决此问题,其中之一是:

compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.0'

像这样使用:

<com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:src="@drawable/your_drawable"/>

使用自定义视图

除了使用现有库之外,您还可以自己编写自定义视图,例如:

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;

public class ScalableImageView extends ImageView {

    boolean adjustViewBounds;

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

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

    public ScalableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setAdjustViewBounds(boolean adjustViewBounds) {
        this.adjustViewBounds = adjustViewBounds;
        super.setAdjustViewBounds(adjustViewBounds);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        if (adjustViewBounds) {
            int drawableWidth = drawable.getIntrinsicWidth();
            int drawableHeight = drawable.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) {
                int height = heightSize;
                int width = height * drawableWidth / drawableHeight;
                if (isInScrollingContainer())
                    setMeasuredDimension(width, height);
                else
                    setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
            } else if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
                int width = widthSize;
                int height = width * drawableHeight / drawableWidth;
                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 parent = getParent();
        while (parent != null && parent instanceof ViewGroup) {
            if (((ViewGroup) parent).shouldDelayChildPressedState()) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }
}

...您将按如下方式使用(XML):

<com.YOUR_PACKE_NAME.ScalableImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:src="@drawable/your_drawable" />
于 2016-11-28T11:47:11.453 回答
0

这是我可以让它工作的唯一方法,让第二个 ImageView 位于中心并且比第一个 ImageView 小,而 TextView 在第二个 ImageView 下。

不幸的是,它在第​​二个 ImageView 上使用了固定的“200dp”图像尺寸,因此在不同尺寸的设备上看起来并不相同。

它还破坏了我的 ViewFlipper,因为我在第二个 ImageView 和 TextView 周围尝试的任何布局都会使它们移动或调整大小。

<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >
    <ImageView
        android:id="@+id/imageview1"
        android:contentDescription="@string/desc"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:src="@drawable/background" />
    <ImageView
        android:id="@+id/imageview2"
        android:layout_centerInParent="true"
        android:contentDescription="@string/desc"
        android:layout_height="200dp"
        android:layout_width="200dp" 
        android:adjustViewBounds="true"
        android:src="@drawable/image2" />
    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@id/imageview2"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        android:gravity="center"
        android:textSize="26sp"
        android:textColor="#333"
        android:background="#fff"
        android:text="this is the text under the image right here"
        />
</RelativeLayout>
于 2013-10-31T23:46:14.487 回答