Як масштабувати зображення в ImageView, щоб зберегти співвідношення сторін


526

В Android я визначив ImageView, що layout_widthмає бути fill_parent(що займає всю ширину телефону).

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

Я дізнаюся, що вгорі та внизу є білий пробіл, ImageViewколи Android масштабує зображення, яке більше, ніж ImageView. Це правда? Якщо так, то як я можу усунути цей простір?

Відповіді:


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

  2. Ви також повинні побачити, android:adjustViewBoundsяк зробити розмір ImageView сам, щоб він міг змінити масштаб зображення. Наприклад, якщо у вас є прямокутне зображення у тому, що зазвичай було б квадратним ImageView, налаштування ViewVounds = true зробить розмір ImageView також прямокутним. Потім це впливає на те, як інші представлення розміщені навколо ImageView.

    Потім, як писав Самух, ви можете змінити спосіб, за яким за замовчуванням масштабує зображення, використовуючи android:scaleTypeпараметр. До речі, найпростішим способом виявити, як це працює, просто було б трохи експериментувати самостійно! Просто пам’ятайте, щоб подивитися на макети самого емулятора (або власне телефону), оскільки попередній перегляд у Eclipse зазвичай неправильний.


18
Це те саме, що щойно зроблено в коді, а не XML. setImageBitmapте саме, що android:src="..."і setBackground...єandroid:background="..."
Стів Хейлі

4
@SuperUser також image.setImageDrawable(...)знаходиться android:src="..."в xml.
PureSpider

11
"android: prilagodViewBounds" тут є зручним для відзначення! якщо цього не додати, у вас, швидше за все, виникнуть проблеми із неправильним масштабуванням рамки / меж / контейнера ImageView.
Сердитий 84

2
src = vs background = була для мене різниця!
Крістофер Ратгеб

21
android:adjustViewBoundsбула останньою частиною моєї головоломки, дякую!
тематика

281

Див android:adjustViewBounds.

Встановіть це значення true, якщо ви хочете, щоб ImageView коригував його межі, щоб зберегти співвідношення сторін для малювання.


6
Це правильне виправлення проблеми. Ми мали це на нашому зображенні, де висота включала весь цей додатковий пробіл. Це не "прозорі пікселі", оскільки ми мали "fill_parent" по ширині, а wrap_content - по висоті. Якщо у вас немає настройкиViewBounds = true, ви отримаєте додатковий пробіл. Після встановлення цього значення наше питання вийшло з ладу. Дякую!
christophercotton

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"? Він також не обріже зображення, але забезпечить, щоб ширина та висота були меншими або рівними ширині та висоті перегляду зображень :) Ось хороший візуальний посібник для скелетів: thinkbot.com/blog/android-imageview-scaletype-a-visual- путівник
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);

Мені знадобилось певний час, щоб це працювало, але це, здається, працює в тих випадках, коли зображення менше ширини екрана і більше ширини екрана, і зображення не позначає вікном.


1
Чому б не просто використовувати android: scaleType = "centerCrop"?
Лукас Батто

працює як шарм, дякую. scaleType залежать від ситуації, наприклад, мені було потрібно саме це.
Давид

Це трохи варварський спосіб змінити розмір виду. Що станеться, якщо межі перегляду зміниться після встановлення растрової карти на ImageView? Ось чому це слід робити в onMeasure (), який можна реалізувати, якщо створити спеціальний підклас ImageView.
Арон Лорінц

1
Все, що мені було потрібно - це fitCenter та prilagodViewBounds, решта коду, принаймні, для мене була непотрібною
kingargyle

Це працює для мене, і не потрібно додавати код. Без настройкиViewBounds, якщо ширина зображення була меншою, ніж ширина imageView, вона не збільшувала масштаб, тому висота зупинялася на початковій висоті, а на ширині з'являлися деякі смуги.
Крісті Балуша

15

Це працювало для мене:

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="39dip"
android:scaleType="centerCrop"
android:adjustViewBounds ="true"


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розміри.


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"/>

Потім у коді я встановив течію як:

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


4

Якщо якість зображення знижується: використовуйте

android:adjustViewBounds="true"

замість

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

3

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

imageView.setScaleType(ScaleType.FIT_XY);

де imageView - це представлення, що представляє ваш ImageView


4
Ні, це змінює співвідношення аспектів. Документи кажуть: "Масштабуйте в X і Y незалежно, щоб src точно відповідав dst. Це може змінити співвідношення сторін src."
Роза Перроне

До речі, цей FIT_XY не можна використовувати для зміни ширини / висоти зображення для відображення на перегляді зображення.
Бей

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);

3

Виконуючи це програмно, обов'язково зателефонуйте сетерам у правильному порядку:

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)

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"

Наведений вище приклад працював для мене.


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>

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); Існує ще багато методів відповідно до вашої вимоги


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);
    }


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" />

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.