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

526

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

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

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

Майкл
источник

Ответы:

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

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

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

Стив Хейли
источник
18
Это то же самое, только в коде, а не в XML. setImageBitmapтакой же, как android:src="..."и setBackground...естьandroid:background="..."
Стив Хейли
4
@SuperUser image.setImageDrawable(...)находится android:src="..."в XML , а также.
PureSpider
11
"Android: AdjustViewBounds" является удобным, чтобы заметить! если вы не добавите это, скорее всего, у вас будут проблемы с неправильным масштабированием границы / границ / контейнера ImageView.
Сердитый 84
2
src = vs background = была разница для меня!
Кристофер Ратхеб
21
android:adjustViewBoundsбыла последней частью моей головоломки, спасибо!
themarketka
281

См android:adjustViewBounds.

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

Gratzi
источник
6
Это правильное решение проблемы. У нас было это на нашем изображении, где высота включала все эти дополнительные пробелы. Это не «прозрачные пиксели», так как у нас был fill_parent для ширины и wrap_content для высоты. Если у вас нет AdjustViewBounds = true, тогда вы получите дополнительный пробел. После того как мы установили значение true, наша проблема исчезла. Спасибо!
Кристоферкоттон
3
спасибо, это и установка src вместо фона работала отлично!
Кэмерон
1
Это идеальное решение проблемы. Также для размеров используйте родительский контейнер, чтобы установить размер, и установите match_parent в ImageView. Это решает много неприятностей.
Нимила Хиранья
+1 за то, чтобы добраться до сути. Первоначально я написал это в более «разговорной» фразе и мягко запретил мне представлять ее. Вместо того, чтобы взъерошить перья, пошел ПК.
Джексонкр
168

Для всех, кто имеет эту конкретную проблему. У вас есть то, ImageViewчто вы хотите, чтобы ширина fill_parentи высота пропорционально масштабировались:

Добавьте эти два атрибута к вашему ImageView:

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

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

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

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
Кевин Паркер
источник
16
Да, но ваше изображение обрезается. Идеальное решение будет растягиваться по ширине, сохранять пропорции и не обрезать. Я понятия не имею, почему это так раздражает ...
Warpzit
1
Я тоже :( Извините, если мое решение не помогло вам, но оно помогло мне.
Кевин Паркер
2
Кевин, то, что вы сказали, было именно тем, что я искал, если размер изображения меньше размера экрана, изображение будет увеличено и отцентрировано, идеально. Спасибо.
Сохам
1
+1, кроме «(или другого View)». AFAICT нет другого представления adjustViewBoundsили scaleTypeатрибутов.
LarsH
как насчет использования android: scaleType = "centerInside" вместо android: scaleType = "centerCrop"? Это также не обрезало бы изображение, но гарантировало бы, что ширина и высота меньше или равны ширине и высоте просмотра изображения :) Вот хорошее визуальное руководство для scaletypes: мыслиbot.com/
Vida
57

Если вы хотите, 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);

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

Kevin
источник
1
Почему бы просто не использовать android: scaleType = "centerCrop"?
Лукас Батто
работает как шарм, спасибо. scaleType зависит от ситуации, например, мне нужно было именно это.
Дэвид
Это немного варварский способ изменить размер представления. Что произойдет, если границы вида изменятся после установки растрового изображения в ImageView? Вот почему это должно быть сделано в onMeasure (), который может быть реализован, если вы создадите пользовательский подкласс ImageView.
Арон Лоринц
1
Все, что мне было нужно, это FitCenter и AdjustViewBounds, остальная часть кода по крайней мере для меня была ненужной
kingargyle
Это работает для меня и не нужно добавлять какой-либо код. Без AdjustViewBounds, если ширина изображения была меньше ширины imageView, она не увеличивалась, поэтому высота останавливалась до исходной высоты, и по ширине некоторые полосы появлялись.
Cristi Băluță
15

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

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="39dip"
android:scaleType="centerCrop"
android:adjustViewBounds ="true"
Mike6679
источник
10

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

android:adjustViewBounds="true"
android:scaleType="fitXY"
Шафик-Ур-Рехман
источник
Это не сохраняет соотношение сторон изображения для меня.
Дмитрий
9

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

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);
Мукеш Пармар
источник
8

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

Samuh
источник
6

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

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

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />
Атиф Махмуд
источник
Только этот ответ помог мне. Спасибо!
Дмитрий
6

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

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

Затем в коде я установил drawable как:

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

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

Джит
источник
5

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

<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, они, скорее всего, будут перекрываться изображением.

halxinate
источник
4

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

android:adjustViewBounds="true"

вместо

android:adjustViewBounds="true"
android:scaleType="fitXY"
developerSumit
источник
3

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

imageView.setScaleType(ScaleType.FIT_XY);

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

oneConsciousness
источник
4
Нет, это меняет соотношение сторон. Документы говорят: «Масштабируйте по X и Y независимо, чтобы src точно совпадал с dst. Это может изменить соотношение сторон src».
Роуз Перроне
Кстати, этот FIT_XY нельзя использовать для изменения ширины / высоты изображения для отображения на изображении.
Bay
3

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

 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);
android_developer
источник
3

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

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)
Lukas
источник
2

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

android:layout_weight="1"
android:scaleType="fitCenter"
Мохсен Афшин
источник
2

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

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

Ключ в родительском совпадении для ширины и высоты

Рому Диззи
источник
1

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

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

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

ITisha
источник
1
Android: layout_weight = "1" является ключом.
Нима
1

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

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

Парт Капур
источник
0

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

<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" />
Флавио Капаччо
источник
0

в случае использования 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>
lvl4fi4
источник
0

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

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

Niraj
источник
0

Передайте свой 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);
    }

ppreetikaa
источник
0

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

<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" />
myworldbox
источник
-5
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 130, 110, false));
user2099162
источник