Подогнать изображение в ImageView, сохранить соотношение сторон, а затем изменить его размер до размеров изображения? - PullRequest
150 голосов
/ 22 ноября 2011

Как подогнать изображение произвольного размера к ImageView?Когда:

  • Первоначально ImageView размеры составляют 250dp * 250dp
  • Размер изображения должен быть увеличен / уменьшен до 250dp
  • Изображение должно сохранять свой аспектratio
  • Размеры ImageView должны соответствовать размерам масштабированного изображения после масштабирования

Например, для изображения 100 * 150 изображение и ImageView должны составлять 166 * 250.Например, для изображения 150 * 100 изображение и ImageView должны быть 250 * 166.

Если я устанавливаю границы как

<ImageView
    android:id="@+id/picture"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:adjustViewBounds="true" />

, то изображения правильно помещаются в ImageView, но ImageView всегда 250dp * 250dp.

Ответы [ 14 ]

205 голосов
/ 11 октября 2013

Может не быть ответом на этот конкретный вопрос, но если кто-то, как и я, ищет ответ, как подогнать изображение в ImageView с ограниченным размером (например, maxWidth), сохранив соотношение сторон, а затем избавиться от чрезмерного пространство, занимаемое ImageView, тогда самое простое решение - использовать следующие свойства в XML:

    android:scaleType="centerInside"
    android:adjustViewBounds="true"
131 голосов
/ 23 ноября 2011

(Ответ был сильно изменен после пояснений к исходному вопросу)

После уточнений:
Это не может быть сделано только в xml . Невозможно масштабировать как изображение, так и ImageView, так что один размер изображения всегда будет 250dp, а ImageView будет иметь те же размеры, что и изображение.

Этот код масштабирует Drawable от ImageView, чтобы оставаться в квадрате, например 250dp x 250dp с одним измерением точно 250dp и сохраняя соотношение сторон. Затем размер ImageView изменяется в соответствии с размерами масштабированного изображения. Код используется в деятельности. Я проверил это с помощью обработчика нажатия кнопки.

Наслаждайтесь. :)

private void scaleImage(ImageView view) throws NoSuchElementException  {
    // Get bitmap from the the ImageView.
    Bitmap bitmap = null;

    try {
        Drawable drawing = view.getDrawable();
        bitmap = ((BitmapDrawable) drawing).getBitmap();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("No drawable on given view");
    } catch (ClassCastException e) {
        // Check bitmap is Ion drawable
        bitmap = Ion.with(view).getBitmap();
    }

    // Get current dimensions AND the desired bounding box
    int width = 0;

    try {
        width = bitmap.getWidth();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("Can't find bitmap on given view/drawable");
    }

    int height = bitmap.getHeight();
    int bounding = dpToPx(250);
    Log.i("Test", "original width = " + Integer.toString(width));
    Log.i("Test", "original height = " + Integer.toString(height));
    Log.i("Test", "bounding = " + Integer.toString(bounding));

    // Determine how much to scale: the dimension requiring less scaling is
    // closer to the its side. This way the image always stays inside your
    // bounding box AND either x/y axis touches it.  
    float xScale = ((float) bounding) / width;
    float yScale = ((float) bounding) / height;
    float scale = (xScale <= yScale) ? xScale : yScale;
    Log.i("Test", "xScale = " + Float.toString(xScale));
    Log.i("Test", "yScale = " + Float.toString(yScale));
    Log.i("Test", "scale = " + Float.toString(scale));

    // Create a matrix for the scaling and add the scaling data
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);

    // Create a new bitmap and convert it to a format understood by the ImageView 
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth(); // re-use
    height = scaledBitmap.getHeight(); // re-use
    BitmapDrawable result = new BitmapDrawable(scaledBitmap);
    Log.i("Test", "scaled width = " + Integer.toString(width));
    Log.i("Test", "scaled height = " + Integer.toString(height));

    // Apply the scaled bitmap
    view.setImageDrawable(result);

    // Now change ImageView's dimensions to match the scaled image
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);

    Log.i("Test", "done");
}

private int dpToPx(int dp) {
    float density = getApplicationContext().getResources().getDisplayMetrics().density;
    return Math.round((float)dp * density);
}

XML-код для ImageView:

<ImageView a:id="@+id/image_box"
    a:background="#ff0000"
    a:src="@drawable/star"
    a:layout_width="wrap_content"
    a:layout_height="wrap_content"
    a:layout_marginTop="20dp"
    a:layout_gravity="center_horizontal"/>


Благодаря этой дискуссии за масштабирующий код:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html


ОБНОВЛЕНИЕ 7 ноября 2012 г .:
Добавлена ​​проверка нулевого указателя, как предлагается в комментариях

40 голосов
/ 10 декабря 2013
<ImageView android:layout_width="match_parent"
           android:layout_height="wrap_content"
           android:scaleType="centerCrop"
           android:adjustViewBounds="true"/>
21 голосов
/ 15 января 2014

Код ниже делает растровое изображение идеально с таким же размером изображения. Получите высоту и ширину растрового изображения, а затем рассчитайте новую высоту и ширину с помощью параметров изображения. Это даст вам необходимое изображение с лучшим соотношением сторон.

int currentBitmapWidth = bitMap.getWidth();
int currentBitmapHeight = bitMap.getHeight();

int ivWidth = imageView.getWidth();
int ivHeight = imageView.getHeight();
int newWidth = ivWidth;

newHeight = (int) Math.floor((double) currentBitmapHeight *( (double) new_width / (double) currentBitmapWidth));

Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap, newWidth, newHeight, true);

imageView.setImageBitmap(newbitMap)

наслаждаться.

12 голосов
/ 01 июля 2013

попробуйте добавить android:scaleType="fitXY" к вашему ImageView.

7 голосов
/ 08 марта 2014

После поиска дня, я думаю, что это самое простое решение:

imageView.getLayoutParams().width = 250;
imageView.getLayoutParams().height = 250;
imageView.setAdjustViewBounds(true);
6 голосов
/ 21 декабря 2017

Лучшее решение, которое работает в большинстве случаев -

Вот пример:

<ImageView android:id="@+id/avatar"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:scaleType="fitXY"/>
5 голосов
/ 07 сентября 2016

все это можно сделать с помощью XML ... другие методы кажутся довольно сложными.В любом случае, вы просто устанавливаете высоту на то, что вам нужно в dp, а затем устанавливаете ширину для переноса содержимого или наоборот.Используйте scaleType fitCenter для настройки размера изображения.

<ImageView
    android:layout_height="200dp"
    android:layout_width="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"
    android:src="@mipmap/ic_launcher"
    android:layout_below="@+id/title"
    android:layout_margin="5dip"
    android:id="@+id/imageView1">
4 голосов
/ 20 ноября 2015

Используйте этот код:

<ImageView android:id="@+id/avatar"
           android:layout_width="fill_parent"
           android:layout_height="match_parent"
           android:scaleType="fitXY" />
4 голосов
/ 13 августа 2014

Отредактировано Ярно Аргиландерс ответ:

Как подогнать изображение под ваши ширину и высоту:

1) Инициализировать ImageView и установить Image:

iv = (ImageView) findViewById(R.id.iv_image);
iv.setImageBitmap(image);

2) Теперь измените размер:

scaleImage(iv);

Отредактировано scaleImage метод: ( вы можете заменить ОЖИДАЕМЫЕ ограничивающие значения )

private void scaleImage(ImageView view) {
    Drawable drawing = view.getDrawable();
    if (drawing == null) {
        return;
    }
    Bitmap bitmap = ((BitmapDrawable) drawing).getBitmap();

    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int xBounding = ((View) view.getParent()).getWidth();//EXPECTED WIDTH
    int yBounding = ((View) view.getParent()).getHeight();//EXPECTED HEIGHT

    float xScale = ((float) xBounding) / width;
    float yScale = ((float) yBounding) / height;

    Matrix matrix = new Matrix();
    matrix.postScale(xScale, yScale);

    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth();
    height = scaledBitmap.getHeight();
    BitmapDrawable result = new BitmapDrawable(context.getResources(), scaledBitmap);

    view.setImageDrawable(result);

    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);
}

и .xml:

<ImageView
    android:id="@+id/iv_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal" />
...