it-roy-ru.com

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

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

Это источник изображения размером 50 x 50 пикселей. Но соотношение сторон не сохраняется - высота ImageView составляет 50 пикселей, а не 100 пикселей (т.е. adjustViewBounds не работает). Если у меня есть картинка 200x200px, она работает - ширина и высота 100px. Этот код приводит к изображению шириной 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>
36
fhucho

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

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

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

65
Roman Nurik

Есть более простой способ. Сделайте ваш 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);
}
11
vladexologija

В дополнение к @ RomanNurik's ответ

Вы можете найти рабочее решение здесь , либо скопировать-вставить код, либо просто добавить зависимость Gradle

dependencies {
    compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.1'
}

Постскриптум Решение, предоставленное @Nilzor, не работает для меня

2
duviteck

У меня было похожее требование; в моем случае я хотел, чтобы изображение было квадратным, и чтобы 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);
    }
}
0
sam