Bagaimana skala Gambar di ImageView untuk menjaga rasio aspek

526

Di Android, saya mendefinisikan ImageView's layout_widthto be fill_parent(yang mengambil lebar penuh ponsel).

Jika gambar yang saya masukkan ImageViewlebih besar dari itu layout_width, Android akan skala itu, kan? Tapi bagaimana dengan tinggi? Saat Android mengukur gambar, apakah ini akan menjaga rasio aspek?

Apa yang saya temukan adalah ada ruang putih di bagian atas dan bawah ImageView ketika Android skala gambar yang lebih besar dari ImageView. Benarkah? Jika ya, bagaimana saya bisa menghilangkan ruang putih itu?

michael
sumber

Jawaban:

799
  1. Ya, secara default Android akan menurunkan skala gambar Anda agar sesuai dengan ImageView, mempertahankan rasio aspek. Namun, pastikan Anda mengatur gambar ke ImageView menggunakan android:src="..."daripada android:background="...". src=membuatnya skala gambar mempertahankan aspek rasio, tetapi background=membuatnya skala dan mendistorsi gambar agar pas dengan ukuran ImageView. (Anda dapat menggunakan latar belakang dan sumber sekaligus, yang dapat berguna untuk hal-hal seperti menampilkan bingkai di sekitar gambar utama, menggunakan hanya satu ImageView.)

  2. Anda juga harus melihat android:adjustViewBounds untuk membuat ukuran ImageView itu sendiri agar sesuai dengan gambar yang diubah ulang. Sebagai contoh, jika Anda memiliki gambar persegi panjang dalam apa yang biasanya menjadi ImageView persegi, adjustViewBounds = true akan membuatnya mengubah ukuran ImageView menjadi persegi panjang juga. Ini kemudian memengaruhi bagaimana Tampilan lain diletakkan di sekitar ImageView.

    Kemudian seperti yang ditulis Samuh, Anda dapat mengubah cara standarnya menskala gambar menggunakan android:scaleTypeparameter. Ngomong-ngomong, cara termudah untuk menemukan bagaimana ini bekerja adalah dengan sedikit bereksperimen sendiri! Hanya ingat untuk melihat tata letak di emulator itu sendiri (atau telepon yang sebenarnya) karena pratinjau di Eclipse biasanya salah.

Steve Haley
sumber
18
Itu hal yang sama, hanya dilakukan dalam kode daripada XML. setImageBitmapadalah sama dengan android:src="..."dan setBackground...adalahandroid:background="..."
Steve Haley
4
@SuperUser juga image.setImageDrawable(...)ada android:src="..."di xml.
PureSpider
11
"android: adjustViewBounds" adalah yang berguna untuk diperhatikan! jika Anda tidak menambahkan ini, kemungkinan besar Anda akan memiliki masalah dengan batas ImageView / batas / wadah tidak scaling dengan benar.
Marah 84
2
src = vs background = adalah perbedaan bagi saya!
Christopher Rathgeb
21
android:adjustViewBoundsadalah bagian terakhir dari teka-teki saya, terima kasih!
themarketka
281

Lihat android:adjustViewBounds.

Setel ini menjadi true jika Anda ingin ImageView menyesuaikan batasnya untuk mempertahankan rasio aspek yang dapat digambar.

Gratzi
sumber
6
Ini adalah perbaikan yang tepat untuk masalah ini. Kami memiliki ini pada tampilan gambar kami, di mana tingginya termasuk semua spasi tambahan ini. Ini bukan "piksel transparan", karena kami memiliki fill_parent untuk lebar, dan wrap_content untuk tinggi. Jika Anda tidak memiliki adjustViewBounds = true, maka Anda mendapatkan spasi kosong tambahan. Setelah menetapkan itu menjadi kenyataan, masalah kami hilang. Terima kasih!
christophercotton
3
terima kasih, ini dan mengaturnya ke src bukannya latar belakang bekerja dengan sempurna!
Cameron
1
Ini adalah perbaikan yang sempurna untuk masalah ini. Juga untuk ukuran, gunakan wadah induk untuk mengatur ukuran, dan atur match_parent di ImageView. Ini memecahkan banyak masalah.
Nimila Hiranya
+1 untuk sampai pada intinya. Saya awalnya menulis itu dalam frasa yang lebih "sehari-hari" dan sof melarang saya mengirimkannya. Daripada mengacak-acak bulu PC pergi.
Jacksonkr
168

Kepada siapa pun yang memiliki masalah khusus ini. Anda memiliki ImageViewlebar yang Anda inginkanfill_parent dan tinggi diskalakan secara proporsional:

Tambahkan dua atribut ini ke ImageView:

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

Dan atur ImageViewlebar ke fill_parentdan tinggi kewrap_content .

Selain itu, jika Anda tidak ingin gambar Anda dipotong, coba ini:

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
Kevin Parker
sumber
16
Ya tapi gambar Anda terpotong. Solusi sempurna akan meregang ke lebar, mempertahankan rasio aspek dan tidak memotong. Saya tidak tahu mengapa ini harus dilakukan ...
Warpzit
1
Saya juga :( Maaf jika solusi saya tidak membantu Anda, tetapi itu membantu saya.
Kevin Parker
2
Kevin, apa yang Anda katakan adalah persis apa yang saya cari, jika ukuran gambar kurang dari layar, diperbesar dan dipusatkan, sempurna. Terima kasih.
Soham
1
+1, kecuali untuk "(atau lainnya View)". AFAICT tidak memiliki tampilan adjustViewBoundsatau scaleTypeatribut lainnya.
LarsH
bagaimana dengan menggunakan android: scaleType = "centerInside" alih-alih android: scaleType = "centerCrop"? Itu juga tidak akan memotong gambar tetapi memastikan bahwa lebar dan tinggi keduanya kurang dari atau sama dengan lebar dan tinggi tampilan gambar :) Ini adalah panduan visual yang bagus untuk skaletipe: thoughtbot.com/blog/android-imageview-scaletype-a-visual- panduan
vida
57

Jika Anda ingin ImageViewyang kedua skala naik dan turun sambil menjaga rasio aspek yang tepat, tambahkan ini ke XML Anda:

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

Tambahkan ini ke kode Anda:

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

Butuh beberapa saat untuk membuat ini berfungsi, tetapi ini tampaknya berfungsi dalam kedua kasus di mana gambar lebih kecil dari lebar layar dan lebih besar dari lebar layar, dan itu tidak mengotak gambar.

Kevin
sumber
1
Mengapa tidak menggunakan android: scaleType = "centerCrop"?
Lukas Batteau
bekerja seperti pesona, terima kasih. scaleType tergantung pada situasi, misalnya saya membutuhkan ini.
David
Ini sedikit cara biadab untuk mengubah ukuran tampilan. Apa yang terjadi jika batas tampilan berubah setelah Anda mengatur bitmap ke ImageView? Inilah mengapa itu harus dilakukan di onMeasure (), yang dapat diimplementasikan jika Anda membuat subkelas kustom dari ImageView.
Aron Lorincz
1
Yang saya butuhkan adalah fitCenter dan AdjustViewBounds, sisa kode setidaknya untuk saya tidak perlu
kingargyle
Ini berfungsi untuk saya dan tidak perlu menambahkan kode apa pun. Tanpa AdjustViewBounds jika lebar gambar lebih kecil dari lebar imageView, itu tidak naik, sehingga tingginya berhenti ke ketinggian asli dan pada lebar beberapa band memang muncul.
Cristi Băluță
15

Ini bekerja untuk saya:

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

ini menyelesaikan masalah saya

android:adjustViewBounds="true"
android:scaleType="fitXY"
shafiq-ur-rehman
sumber
Itu tidak mempertahankan rasio aspek gambar untuk saya.
Dmitry
9

Kode di bawah ini Berfungsi untuk gambar skala sebagai aspek rasio:

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);
Mukesh Parmar
sumber
8

Lihatlah ImageView.ScaleType untuk mengontrol dan memahami cara mengubah ukuran terjadi dalam ImageView. Ketika gambar diubah ukurannya (sambil mempertahankan rasio aspeknya), kemungkinan tinggi atau lebar gambar menjadi lebih kecil dari ImageViewdimensi.

Samuh
sumber
6

Gunakan properti ini di ImageView untuk menjaga rasio aspek:

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

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />
Atif Mahmood
sumber
Hanya jawaban ini yang membantu saya. Terima kasih!
Dmitry
6

Inilah cara kerjanya bagi saya di dalam ConstraintLayout:

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

Kemudian dalam kode, saya mengatur drawable sebagai:

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

Ini cocok dengan gambar sesuai rasio aspeknya dan membuatnya tetap di tengah.

Jeet
sumber
5

Saya memiliki gambar yang lebih kecil dari layar. Untuk membuatnya membentang secara proporsional ke max dan berpusat pada tampilan saya harus menggunakan kode berikut:

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

Namun perlu diingat, bahwa jika Anda memiliki tata letak relatif dan mengatur beberapa elemen di atas atau di bawah ImageView, kemungkinan besar akan tumpang tindih dengan gambar.

halxinate
sumber
4

Jika kualitas gambar menurun: gunakan

android:adjustViewBounds="true"

dari pada

android:adjustViewBounds="true"
android:scaleType="fitXY"
developerSumit
sumber
3

Bagi Anda yang menginginkan gambar agar pas dengan tampilan gambar dengan penskalaan yang tepat dan tanpa pemangkasan digunakan

imageView.setScaleType(ScaleType.FIT_XY);

di mana imageView adalah tampilan yang mewakili ImageView Anda

satuKesadaran
sumber
4
Tidak, ini mengubah rasio aspek. Dokumen mengatakan: "Skala dalam X dan Y secara independen, sehingga src sama persis dengan dst. Ini dapat mengubah rasio aspek dari src."
Rose Perrone
Omong-omong, FIT_XY ini tidak dapat digunakan untuk mengubah lebar / tinggi gambar untuk ditampilkan pada tampilan gambar.
Bay
3

Anda dapat menghitung lebar layar. Dan Anda dapat skala bitmap.

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

menghitung lebar layar dan menskalakan tinggi gambar berdasarkan lebar layar.

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

Setelah Anda bisa skala bitmap.

Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, (int) screenWidth, (int) newHeight, true);
android_developer
sumber
3

Saat melakukan ini secara terprogram, pastikan untuk memanggil setter dengan urutan yang benar:

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)
lukas
sumber
2

Jika Anda ingin gambar Anda menempati ruang maksimum yang mungkin maka opsi terbaik adalah

android:layout_weight="1"
android:scaleType="fitCenter"
Mohsen Afshin
sumber
2

Anda tidak memerlukan kode java. Anda hanya perlu:

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

Kuncinya ada di induk pertandingan untuk lebar dan tinggi

Romu Dizzy
sumber
1

Coba gunakan android:layout_gravityuntuk ImageView:

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

Contoh di atas berhasil untuk saya.

ITisha
sumber
1
android: layout_weight = "1" adalah kuncinya.
nima
1

Saya memiliki algoritme untuk skala bitmap untuk menyesuaikan dimensi wadah, mempertahankan rasio aspeknya. Silakan temukan solusi saya di sini

Semoga ini bisa membantu seseorang di jalan kecil!

Parth Kapoor
sumber
0

Saya menggunakan ini:

<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" />
Flavio Capaccio
sumber
0

dalam hal menggunakan cardviewuntuk pembulatan imageviewdan diperbaiki android:layout_heightuntuk header ini bekerja untuk saya memuat gambar denganGlide

    <?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
sumber
0

Anda dapat mengatur skala gambar yang juga akan mengurangi ukuran gambar Anda. Ada perpustakaan untuk itu Anda dapat mengunduh dan menggunakannya. https://github.com/niraj124124/Images-Files-scale-and-compress.git

Cara menggunakan 1) Impor kompresor-v1.0. jar ke proyek Anda. 2) Tambahkan kode sampel di bawah ini untuk diuji. ResizeLimiter resize = ImageResizer.build (); resize.scale ("inputImagePath", "outputImagePath", imageWidth, imageHeight); Banyak lagi metode yang ada sesuai dengan kebutuhan Anda

Niraj
sumber
0

Lewati ImageView Anda dan berdasarkan tinggi dan lebar layar Anda dapat membuatnya

    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
sumber
0

Jawaban cepat:

<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
sumber
-5
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 130, 110, false));
pengguna2099162
sumber