Подтвердить что ты не робот

ImageView adjustViewBounds не работает

У меня есть ImageView с android:layout_width=100dp, android:layout_height=wrap_content и android:adjustViewBounds=true

Источник - это 50 x 50 пикселей. Но соотношение сторон не сохраняется - высота ImageView составляет 50 пикселей, а не 100 пикселей (т.е. adjustViewBounds не работает). Если у меня есть изображение 200x200px, оно работает - ширина и высота - 100 пикселей. Этот код дает изображение шириной 100 пикселей и размером 50 пикселей, но изображение src равно квадрату:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <ImageView
        android:id="@+id/photo"
        android:src="@drawable/icon"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:scaleType="fitXY"
        android:adjustViewBounds="true" />

</LinearLayout>
4b9b3361

Ответ 1

Проблема заключается в том, что adjustViewBounds не будет увеличивать размер ImageView за пределами естественных размеров извлекаемого. Он будет только уменьшать представление, чтобы поддерживать соотношение сторон; если вы предоставили изображение размером 500x500 вместо изображения 50x50, это должно работать.

Если вам интересно, где это поведение реализовано, см. ImageView.java onMeasure.

Одним из способов решения является реализация пользовательского ImageView, который изменяет это поведение в onMeasure.

Ответ 2

Там более простой способ. Сделайте свой ImageView следующим:

<ImageView
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:scaleType="fitCenter"
  android:adjustViewBounds="true"/>

Таким образом, drawable будет растягиваться, чтобы поместиться в центре ImageView, сохранив соотношение сторон. Нам просто нужно вычислить правильную высоту, чтобы сделать ее пропорциональной поэтому у нас нет пробелов:

private void setImageBitmap(Bitmap bitmap, ImageView imageView){
    float i = ((float)imageWidth)/((float)bitmap.getWidth());
    float imageHeight = i * (bitmap.getHeight());
    imageView.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth, (int) imageHeight));
    imageView.setImageBitmap(bitmap);
}

Ответ 4

У меня было аналогичное требование; в моем случае я хотел, чтобы изображение было квадратным, и хотел, чтобы ImageView соответствовал соотношению сторон, поэтому я мог использовать его фон и дополнение для рисования границы.

Я прочитал ответы здесь, но вместо того, чтобы переопределять ImageView, я решил создать макет, который гарантирует, что его содержимое (должно быть только одно представление) является квадратным. Таким образом, я мог бы использовать стандартный ImageView внутри него. (И вы никогда не знаете, я мог бы захотеть сделать что-то еще квадратное позже. Хотя, вероятно, нет.)

В случае, если это полезно для кого-то еще, вот код (не стесняйтесь копировать). Вероятно, есть ошибки, поскольку я только что сделал это для моего приложения, а затем остановился.:)

public class SquareLayout extends ViewGroup
{
    public SquareLayout(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

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

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        // Work out width and height, and square size.
        int width = r - l;
        int height = b - t;

        int size, xOffset, yOffset;
        if(width < height)
        {
            size = width;
            xOffset = 0;
            yOffset = (height - size) / 2;
        }
        else
        {
            size = height;
            xOffset = (width - size) / 2;
            yOffset = 0;
        }

        for(int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            child.layout(xOffset, yOffset, size + xOffset, size + yOffset);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // Get width and height.
        int w = -1, h = -1;
        switch(MeasureSpec.getMode(widthMeasureSpec))
        {
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            w = MeasureSpec.getSize(widthMeasureSpec);
            break;

        case MeasureSpec.UNSPECIFIED:
            break;
        }
        switch(MeasureSpec.getMode(heightMeasureSpec))
        {
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            h = MeasureSpec.getSize(heightMeasureSpec);
            break;

        case MeasureSpec.UNSPECIFIED:
            break;
        }

        // If only one of width/height is unspecified, set them both the same.
        if(w == -1 && h != -1)
        {
            w = h;
        }
        else if(h == -1 && w != -1)
        {
            h = w;
        }

        // Either they're both specified or both unspecified.
        int childMeasureSpec;
        if(w == -1)
        {
            childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        else
        {
            childMeasureSpec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
        }

        // Pass through to children.
        int maxDimension = 1;
        for(int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            child.measure(childMeasureSpec, childMeasureSpec);
            maxDimension = Math.max(maxDimension, child.getMeasuredWidth());
            maxDimension = Math.max(maxDimension, child.getMeasuredHeight());
        }

        if(w == -1)
        {
            w = maxDimension;
            h = maxDimension;
        }

        setMeasuredDimension(w, h);
    }
}

Ответ 5

эта строка сделает это за вас android: scaleType = "fitXY"