Как масштабировать изображение в ImageView, чтобы сохранить соотношение сторон

В Android я определил ImageView layout_width как fill_parent (который занимает всю ширину телефона).

Если изображение, которое я помещаю в ImageView, больше, чем layout_width, Android масштабирует его, верно? А как насчет высоты? Когда Android масштабирует изображение, сохранит ли оно соотношение сторон?

Я обнаружил, что есть пробелы вверху и внизу ImageView, когда Android масштабирует изображение, которое больше, чем ImageView. Это правда? Если да, как я могу удалить это пустое пространство?


person michael    schedule 26.03.2010    source источник


Ответы (25)


  1. Да, по умолчанию Android масштабирует ваше изображение до размера ImageView, сохраняя соотношение сторон. Однако убедитесь, что вы устанавливаете изображение в ImageView, используя android:src="...", а не android:background="...". src= заставляет масштабировать изображение с сохранением соотношения сторон, но background= заставляет масштабировать и изображение, чтобы оно точно соответствовало размеру ImageView. (Однако вы можете использовать фон и источник одновременно, что может быть полезно для таких вещей, как отображение рамки вокруг основного изображения, используя только один ImageView.)

  2. Вы также должны увидеть android:adjustViewBounds, чтобы изменить размер ImageView в соответствии с масштабируемым изображением. Например, если у вас есть прямоугольное изображение в том, что обычно является квадратным ImageView, adjustViewBounds = true заставит его также изменить размер ImageView, чтобы он был прямоугольным. Затем это влияет на то, как другие представления располагаются вокруг ImageView.

    Затем, как написал Самух, вы можете изменить способ масштабирования изображений по умолчанию, используя параметр android:scaleType. Кстати, самый простой способ узнать, как это работает, - это немного поэкспериментировать! Просто не забудьте посмотреть макеты в самом эмуляторе (или на реальном телефоне), поскольку предварительный просмотр в Eclipse обычно неверен.

person Steve Haley    schedule 26.03.2010
comment
Спасибо. Но что, если у меня есть ImageView, и я устанавливаю изображение с помощью imageView.setImageBitmap ()? - person michael; 31.03.2010
comment
Это то же самое, только сделано в коде, а не в XML. setImageBitmap то же самое, что android:src="...", а setBackground... это android:background="..." - person Steve Haley; 31.03.2010
comment
@SteveHaley, я знаю, что уже слишком поздно, но не могли бы вы сказать мне эквивалент image.setImageDrawable в xml-коде - person ; 27.04.2013
comment
@SuperUser image.setImageDrawable(...) тоже android:src="..." в xml. - person PureSpider; 03.05.2013
comment
android: adjustViewBounds - это полезный инструмент, на который стоит обратить внимание! если вы не добавите это, у вас, скорее всего, возникнут проблемы с неправильным масштабированием границы / границ / контейнера ImageView. - person Angry 84; 02.02.2014
comment
‹Code› android: scaleType = fitCenter ‹/code› Тоже неплохо работает. Он автоматически обрезается так, чтобы изображение полностью соответствовало просмотру изображения. - person Confuse; 06.09.2014
comment
Имейте в виду, что adjustViewBounds не будет работать, если ImageView имеет точный размер, указанный в layout stackoverflow.com/questions/16022841/ - person southerton; 23.01.2015
comment
Пятно! Блестящий ответ ... сэкономил много кода ... я собирался создать собственный просмотр изображений ... большое спасибо! - person sid_09; 01.08.2015
comment
Это круто! Я нахожу твой ответ на долгое время. До этого я использовал adjustViewBounds и setBackground, это тоже не работало. - person nobjta_9x_tq; 07.08.2015
comment
src = vs background = было для меня разницей! - person Christopher Rathgeb; 20.10.2015
comment
android:adjustViewBounds был последним кусочком моей головоломки, спасибо! - person themarketka; 14.01.2016
comment
Правильный ответ, но я отказался от моего +1, потому что, ИМО, ваше многословие было неоправданным для этого вопроса. Тем не менее, спасибо за ваше время. - person Jacksonkr; 11.03.2016
comment
android: adjustViewBounds = true наконец исправил это для меня. Спасибо. - person Evan Sevy; 13.02.2017

См. android:adjustViewBounds.

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

person Gratzi    schedule 08.07.2010
comment
Это правильное решение проблемы. У нас это было в нашем представлении изображения, где высота включала все эти лишние пробелы. Это не прозрачные пиксели, поскольку у нас есть fill_parent для ширины и wrap_content для высоты. Если у вас нет adjustViewBounds = true, вы получите лишний пробел. После установки этого значения наша проблема исчезла. Спасибо! - person christophercotton; 16.07.2010
comment
спасибо, это и установка src вместо background сработали отлично! - person Cameron; 10.10.2010
comment
Это идеальное решение проблемы. Также для размеров используйте родительский контейнер, чтобы установить размер, и установите match_parent в ImageView. Это решает множество проблем. - person Nimila Hiranya; 25.09.2015
comment
+1 за переход к делу. Изначально я написал это более разговорной фразой и запретил мне подавать его. Вместо того, чтобы взъерошивать перья, пошел ПК. - person Jacksonkr; 11.03.2016
comment
Отличный ответ и отлично сработал - person Satyam Gondhale; 17.03.2021

Всем, у кого есть эта конкретная проблема. У вас есть ImageView, ширина которого должна быть fill_parent, а высота пропорционально масштабируется:

Добавьте эти два атрибута в свой ImageView:

android:adjustViewBounds="true"
android:scaleType="centerCrop"

И установите ширину ImageView на fill_parent и высоту на wrap_content.

Кроме того, если вы не хотите, чтобы ваше изображение было обрезано, попробуйте следующее:

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
person Kevin Parker    schedule 26.05.2011
comment
Да, но ваше изображение обрезается. Идеальное решение - растянуть по ширине, сохранить соотношение сторон, а не обрезать. Понятия не имею, почему это должно быть так утомительно ... - person Warpzit; 16.11.2011
comment
Я тоже :( Извините, если мое решение вам не помогло, но оно помогло мне. - person Kevin Parker; 16.11.2011
comment
Кевин, то, что вы сказали, было именно тем, что я искал, если размер изображения меньше размера экрана, оно увеличивается и центрируется, идеально. Спасибо. - person Soham; 17.01.2013
comment
+1, кроме (или другого View). AFAICT, ни одно другое представление не имеет атрибутов adjustViewBounds или scaleType. - person LarsH; 08.09.2015
comment
как насчет использования android: scaleType = centerInside вместо android: scaleType = centerCrop? Он также не будет обрезать изображение, но гарантирует, что ширина и высота меньше или равны ширине и высоте изображения :) Вот хорошее визуальное руководство для масштабных типов: thinkbot.com/blog/android-imageview-scaletype-a-visual-guide - person vida; 22.01.2020

Если вам нужен ImageView, который масштабируется вверх и вниз при сохранении правильного соотношения сторон, добавьте это в свой XML:

android:adjustViewBounds="true"
android:scaleType="fitCenter"

Добавьте это в свой код:

// We need to adjust the height if the width of the bitmap is
// smaller than the view width, otherwise the image will be boxed.
final double viewWidthToBitmapWidthRatio = (double)image.getWidth() / (double)bitmap.getWidth();
image.getLayoutParams().height = (int) (bitmap.getHeight() * viewWidthToBitmapWidthRatio);

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

person Kevin    schedule 18.03.2012
comment
Почему бы просто не использовать android: scaleType = centerCrop? - person Lukas Batteau; 19.06.2012
comment
работает как шарм, спасибо. scaleType зависит от ситуации, например мне нужно именно это. - person David; 18.01.2013
comment
Это немного варварский способ изменения размера представления. Что произойдет, если границы представления изменятся после того, как вы установите растровое изображение в ImageView? Вот почему это нужно делать в onMeasure (), который можно реализовать, если вы создадите собственный подкласс ImageView. - person Aron Lorincz; 17.03.2014
comment
Все, что мне было нужно, это fitCenter и adjustViewBounds, остальной код, по крайней мере, для меня был не нужен - person kingargyle; 22.05.2015
comment
Это работает для меня, и мне не нужно добавлять код. Без adjustViewBounds, если ширина изображения была меньше ширины imageView, масштабирование не происходило, поэтому высота останавливалась до исходной высоты, а на ширине появлялись некоторые полосы. - person Cristi Băluță; 04.04.2019

Это сработало для меня:

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="39dip"
android:scaleType="centerCrop"
android:adjustViewBounds ="true"
person Mike6679    schedule 28.03.2013

Вот как это сработало для меня внутри ConstraintLayout:

<ImageView
    android:id="@+id/myImg"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"/>

Затем в коде я установил возможность рисования как:

ImageView imgView = findViewById(R.id.myImg);
imgView.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.image_to_show, null));

Это хорошо вписывается в изображение в соответствии с его соотношением сторон и сохраняет его в центре.

person Jeet    schedule 11.06.2019

это решило мою проблему

android:adjustViewBounds="true"
android:scaleType="fitXY"
person shafiq-ur-rehman    schedule 24.04.2017
comment
Для меня это не сохраняет соотношение сторон изображения. - person Dmitry; 23.08.2018

Ниже приведен код, работающий для масштабирования изображения как соотношения сторон:

Bitmap bitmapImage = BitmapFactory.decodeFile("Your path");
int nh = (int) ( bitmapImage.getHeight() * (512.0 / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, 512, nh, true);
your_imageview.setImageBitmap(scaled);
person Mukesh Parmar    schedule 12.09.2014

Взгляните на ImageView.ScaleType, чтобы контролировать и понимать способ изменение размера происходит в ImageView. При изменении размера изображения (при сохранении его соотношения сторон) велика вероятность, что высота или ширина изображения станут меньше размеров ImageView.

person Samuh    schedule 26.03.2010

Используйте эти свойства в ImageView, чтобы сохранить соотношение сторон:

android:adjustViewBounds="true"
android:scaleType="fitXY"

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />
person Atif Mahmood    schedule 05.05.2016
comment
Только этот ответ мне помог. Спасибо! - person Dmitry; 23.08.2018

У меня изображение меньше экрана. Чтобы он был растянут пропорционально максимуму и центрирован в представлении, мне пришлось использовать следующий код:

<ImageView
    android:id="@+id/my_image"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:adjustViewBounds="true"
    android:layout_weight="1"
    android:scaleType="fitCenter" />

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

person halxinate    schedule 02.10.2012

Если качество изображения снижается: используйте

android:adjustViewBounds="true"

вместо того

android:adjustViewBounds="true"
android:scaleType="fitXY"
person developerSumit    schedule 20.12.2018

Для всех, кто хочет, чтобы изображение точно соответствовало изображению с правильным масштабированием и без обрезки.

imageView.setScaleType(ScaleType.FIT_XY);

где imageView - это представление, представляющее ваш ImageView

person oneConsciousness    schedule 10.12.2012
comment
Нет, это меняет соотношение сторон. В документах говорится: Масштабируйте по X и Y независимо, чтобы src точно соответствовал dst. Это может изменить соотношение сторон файла src. - person Rose Perrone; 28.05.2013
comment
Кстати, этот FIT_XY не может использоваться для изменения ширины / высоты изображения для отображения в окне просмотра изображения. - person Bay; 28.02.2018

Вы можете рассчитать ширину экрана. И вы можете масштабировать растровое изображение.

 public static float getScreenWidth(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        float pxWidth = outMetrics.widthPixels;
        return pxWidth;
    }

рассчитать ширину экрана и высоту масштабированного изображения по ширине экрана.

float screenWidth=getScreenWidth(act)
  float newHeight = screenWidth;
  if (bitmap.getWidth() != 0 && bitmap.getHeight() != 0) {
     newHeight = (screenWidth * bitmap.getHeight()) / bitmap.getWidth();
  }

После можно масштабировать растровое изображение.

Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, (int) screenWidth, (int) newHeight, true);
person msevgi    schedule 10.03.2015

Делая это программно, обязательно вызывайте сеттеры в правильном порядке:

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)
person lukas    schedule 06.04.2017

Если вы хотите, чтобы ваше изображение занимало максимально возможное пространство, лучшим вариантом будет

android:layout_weight="1"
android:scaleType="fitCenter"
person Mohsen Afshin    schedule 19.08.2012

Йо не нужен код Java. Вам просто нужно:

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

Ключ находится в соответствующем родительском элементе для ширины и высоты.

person Romu Dizzy    schedule 17.01.2017

Я использую это:

<ImageView
android:id="@+id/logo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:scaleType="centerInside"
android:src="@drawable/logo" />
person Flavio Capaccio    schedule 26.06.2013
comment
Я тоже выставил android:adjustViewBounds="true". centerInside был способом предотвратить обрезку и сохранить соотношение сторон. - person Martin Braun; 04.05.2021

Попробуйте использовать android:layout_gravity для ImageView:

android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_weight="1"

Приведенный выше пример сработал для меня.

person ITisha    schedule 20.08.2013
comment
android: layout_weight = 1 - это ключ. - person nima; 17.10.2014

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

Надеюсь, это поможет кому-то в переулке!

person Parth Kapoor    schedule 08.04.2014

Передайте свой ImageView и в зависимости от высоты и ширины экрана вы можете сделать его

    public void setScaleImage(EventAssetValueListenerView view){
        // Get the ImageView and its bitmap
        Drawable drawing = view.getDrawable();
        Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
        // Get current dimensions
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float xScale = ((float) 4) / width;
        float yScale = ((float) 4) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);

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

        view.setImageDrawable(result);

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

person Community    schedule 04.01.2016

в случае использования cardview для округления imageview и фиксированного android:layout_height для заголовка это помогло мне загрузить изображение с Glide

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="220dp"
             xmlns:card_view="http://schemas.android.com/apk/res-auto"
             >

    <android.support.v7.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center|top"
            card_view:cardBackgroundColor="@color/colorPrimary"
            card_view:cardCornerRadius="10dp"
            card_view:cardElevation="10dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true">

        <ImageView
                android:adjustViewBounds="true"
                android:maxHeight="220dp"
                android:id="@+id/iv_full"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitCenter"/>

    </android.support.v7.widget.CardView>
</FrameLayout>
person lvl4fi4    schedule 07.11.2018

Вы можете масштабировать изображение, что также уменьшит размер вашего изображения. Для этого есть библиотека, которую вы можете скачать и использовать. https://github.com/niraj124124/Images-Files-scale-and-compress.git

Как использовать 1) Импортируйте компрессор-v1.0. jar в свой проект. 2) Добавьте приведенный ниже образец кода для тестирования. ResizeLimiter resize = ImageResizer.build (); resize.scale («inputImagePath», «outputImagePath», imageWidth, imageHeight); Есть еще много методов в соответствии с вашими требованиями

person Niraj    schedule 29.01.2019

Быстрый ответ:

<ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:scaleType="center"
        android:src="@drawable/yourImage"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
person myworldbox    schedule 01.03.2020

Программно применить соотношение сторон к Imageview:

aspectRatio = imageWidth/imageHeight   
ratioOfWidth = imageWidth/maxWidth  
ratioOfHeight = imageHeight/maxHeight  


if(ratioOfWidth > ratioOfHeight){​​​​​​​
    imageWidth = maxWidth 
    imageHeight = imageWidth/aspectRatio
}​​​​​​​ else if(ratioOfHeight > ratioOfWidth){​​​​​​​
    imageHeight = maxHeight
    imageWidth = imageHeight * aspectRatio
}​​​​​​​

После этого вы можете использовать масштабированное растровое изображение для просмотра изображения.

Bitmap scaledBitmap= Bitmap.createScaledBitmap(bitmap, (int) imageWidth , (int) imageHeight , true);
person Kaviyarasan M    schedule 01.12.2020