ImageView - memiliki lebar kecocokan tinggi?

166

Saya memiliki tampilan gambar. Saya ingin lebarnya menjadi fill_parent. Saya ingin tingginya menjadi apa pun yang akhirnya menjadi lebar. Sebagai contoh:

<ImageView
  android:layout_width="fill_parent"
  android:layout_height="whatever the width ends up being" />

Apakah sesuatu seperti itu dimungkinkan dalam file tata letak tanpa harus membuat kelas tampilan saya sendiri?

Terima kasih

pengguna291701
sumber
Apakah Anda mengetahui cara melakukan ini? Saya berasumsi Anda ingin rasio aspek tetap sama. Sebagian besar dari jawaban ini menganggap Anda ingin gambar menjadi persegi.
Adam
@ Jo Blow itu adalah cara yang SANGAT buruk untuk melakukannya
Aggressor

Jawaban:

170

Pembaruan: 14 Sep 2017

Menurut komentar di bawah ini, pustaka dukungan persen tidak digunakan lagi sebagai Pustaka Dukungan Android 26.0.0. Ini adalah cara baru untuk melakukannya:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1" />

</android.support.constraint.ConstraintLayout>

Lihat di sini

Usang:

Menurut pos ini oleh Pengembang Android, yang perlu Anda lakukan sekarang adalah membungkus apa pun yang Anda inginkan dalam PercentRelativeLayout atau PercentFrameLayout, dan kemudian tentukan rasio-rasionya, seperti

<android.support.percent.PercentRelativeLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        app:layout_widthPercent="100%"
        app:layout_aspectRatio="100%"/>

</android.support.percent.PercentRelativeLayout>
davidchuyaya
sumber
8
Tautan jawaban ini memiliki solusi paling elegan yang disediakan Google. Dalam kasus saya, saya ingin gambar ditampilkan dalam rasio 16: 9, apa pun rasio aspek gambar aslinya. Bagus sekali. Terima kasih!
BIARKAN
Im kasus saya, solusi seperti ini tidak berhasil, ini berhasil!
Gooey
5
jangan lupa untuk menambahkan 'kompilasi com.android.support:percent:23.3.0' dalam dependensi Anda
Milad Faridnia
Sepertinya pendekatan ini mengalami masalah dengan WrappedViewPager yang menghitung ketinggian berdasarkan konten anak-anaknya. Sumber untuk WrappedViewPager mirip dengan gist.github.com/egslava/589b82a6add9c816a007
sha
1
Modul Dukungan Persen telah usang telah ditinggalkan sejak perpustakaan dukungan android 26.0.0. Sumber: developer.android.com/topic/libraries/support-library/…
MHogge
97

Mungkin ini akan menjawab pertanyaan Anda:

<ImageView
    android:id="@+id/cover_image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true" />

Anda dapat mengabaikan scaleTypeatribut untuk situasi khusus ini.

Vlad Stefanescu
sumber
12
Yup, itu tidak berguna
Fattie
4
Itu tidak sia-sia sia-sia. Ini berfungsi dengan baik untuk penggunaan saya, saya memiliki ikon pada bilah judul yang ingin saya skala untuk mengisi ketinggian sementara sisa persegi.
Anubian Noob
3
Memecahkan masalah saya juga.
Penjualan Dielson
Cara termudah! Ini harus ditandai sebagai Jawaban Terbaik.
H. Farid
30

Ini dapat dilakukan dengan menggunakan LayoutParams untuk secara dinamis mengatur tinggi Tampilan setelah Anda tahu lebar Tampilan saat runtime. Anda perlu menggunakan utas Runnable untuk mendapatkan lebar Tampilan saat runtime atau Anda akan mencoba mengatur Tinggi sebelum Anda tahu lebar Tampilan karena tata letak belum digambar.

Contoh bagaimana saya memecahkan masalah saya:

final FrameLayout mFrame = (FrameLayout) findViewById(R.id.frame_id);

    mFrame.post(new Runnable() {

        @Override
        public void run() {
            RelativeLayout.LayoutParams mParams;
            mParams = (RelativeLayout.LayoutParams) mFrame.getLayoutParams();
            mParams.height = mFrame.getWidth();
            mFrame.setLayoutParams(mParams);
            mFrame.postInvalidate();
        }
    });

LayoutParams harus dari jenis Tampilan Induk tempat tampilan Anda. FrameLayout saya ada di dalam RelativeLayout dalam file xml.

    mFrame.postInvalidate();

dipanggil untuk memaksa tampilan redraw saat berada di utas terpisah dari utas UI

drees
sumber
4
jawaban yang luar biasa, terutama dengan Runnable, terima kasih!
jesses.co.tt
1
Meskipun ini berfungsi, itu tidak ideal. Berjalan di pos berarti tampilan yang dirender satu kali sebelum tata letak berubah. Bisa memungkinkan flash konten pada ketinggian yang salah, sebelum menggambar dengan benar. Lebih baik dipecahkan sebelumnya. Momen paling awal yang mungkin untuk dipecahkan adalah selama custom onMeasure, seperti yang ditunjukkan dalam jawaban Regis . Alternatif, tetapi hanya untuk tampilan yang diberikan melalui adaptor, misalnya di dalam GridView, adalah jawaban Matt .
ToolmakerSteve
1
baik itu bekerja untuk saya hanya setelah memanggil requestLayout()setelah mengatur parameter. mengapa itu bisa terjadi?
Divins Mathew
mFrame.postInvalidate (); adalah apa yang melakukannya, tanpanya saya mendapatkan pandangan keluar dari posisi.
Jacolack
17

Saya tidak bisa mendapatkan jawaban David Chu bekerja untuk item RecyclerView dan tahu saya perlu membatasi ImageView ke orang tua. Tetapkan lebar ImageView ke 0dpdan membatasi mulai dan berakhir ke induk. Saya tidak yakin apakah mengatur lebar wrap_contentatau match_parentberfungsi dalam beberapa kasus, tapi saya pikir ini adalah cara yang lebih baik untuk mendapatkan anak dari ConstraintLayout untuk mengisi induknya.

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintDimensionRatio="1:1"/>

</android.support.constraint.ConstraintLayout>
Shawn Aten
sumber
13

Di sini saya apa yang saya lakukan untuk memiliki ImageButton yang selalu memiliki lebar sama dengan tingginya (dan menghindari margin kosong bodoh dalam satu arah ... yang saya anggap sebagai bug dari SDK ...):

Saya mendefinisikan kelas SquareImageButton yang memanjang dari ImageButton:

package com.myproject;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageButton;

    public class SquareImageButton extends ImageButton {

        public SquareImageButton(Context context) {
        super(context);


        // TODO Auto-generated constructor stub
    }

    public SquareImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub

    }

    public SquareImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

    }

    int squareDim = 1000000000;

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


        int h = this.getMeasuredHeight();
        int w = this.getMeasuredWidth();
        int curSquareDim = Math.min(w, h);
        // Inside a viewholder or other grid element,
        // with dynamically added content that is not in the XML,
        // height may be 0.
        // In that case, use the other dimension.
        if (curSquareDim == 0)
            curSquareDim = Math.max(w, h);

        if(curSquareDim < squareDim)
        {
            squareDim = curSquareDim;
        }

        Log.d("MyApp", "h "+h+"w "+w+"squareDim "+squareDim);


        setMeasuredDimension(squareDim, squareDim);

    }

}

Inilah xml saya:

<com.myproject.SquareImageButton
            android:id="@+id/speakButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:scaleType="centerInside"
            android:src="@drawable/icon_rounded_no_shadow_144px"
            android:background="#00ff00"
            android:layout_alignTop="@+id/searchEditText"
            android:layout_alignBottom="@+id/searchEditText"
            android:layout_alignParentLeft="true"
           />

Bekerja seperti pesona!

Regis_AG
sumber
Yup, itu jawaban terbaik. (dan satu-satunya yang benar-benar cocok dengan pertanyaan OP)
Twometer
6

Di Android 26.0.0 PercentRelativeLayout telah ditinggalkan .

Cara terbaik untuk menyelesaikannya sekarang dengan ConstraintLayoutseperti ini:

<android.support.constraint.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

    <ImageView android:layout_width="match_parent"
               android:layout_height="0dp"
               android:scaleType="centerCrop"
               android:src="@drawable/you_image"                       
               app:layout_constraintDimensionRatio="1:1"/>


</android.support.constraint.ConstraintLayout>


Berikut ini adalah tutorial tentang cara menambahkan ConstraintLayoutke proyek Anda.

Sebastian Schneider
sumber
6

Jika tampilan gambar Anda berada di dalam tata letak kendala, Anda dapat menggunakan batasan berikut untuk membuat tampilan gambar persegi

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:id="@+id/ivImageView"
    app:layout_constraintDimensionRatio="W,1:1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"/>
ChaturaM
sumber
5

Anda tidak dapat melakukannya dengan tata letak saja, saya sudah mencoba. Saya akhirnya menulis kelas yang sangat sederhana untuk menanganinya, Anda dapat memeriksanya di github. SquareImage.java Bagian dari proyek yang lebih besar tetapi tidak ada sedikit copy dan paste yang tidak dapat diperbaiki (dilisensikan dengan Apache 2.0)

Pada dasarnya Anda hanya perlu mengatur tinggi / lebar sama dengan dimensi lain (tergantung pada cara mana Anda ingin skala itu)

Catatan: Anda bisa membuatnya persegi tanpa kelas khusus menggunakan scaleTypeatribut tetapi batas tampilan melampaui gambar yang terlihat, yang membuatnya menjadi masalah jika Anda menempatkan tampilan lain di dekat itu.

smith324
sumber
3

Untuk mengatur ImageView Anda sama dengan setengah layar, Anda perlu menambahkan berikut ini ke XML Anda untuk ImageView:

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

Untuk mengatur tinggi sama dengan lebar ini, Anda harus melakukannya dalam kode. Dalam getViewmetode GridViewadaptor Anda , atur ImageViewtingginya sama dengan lebarnya yang diukur:

mImageView.getLayoutParams().height = mImageView.getMeasuredWidth();
Matt Logan
sumber
3

Untuk orang yang lewat sekarang, pada 2017, cara terbaik baru untuk mencapai apa yang Anda inginkan adalah dengan menggunakan ConstraintLayout seperti ini:

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="1:1" />

Dan jangan lupa untuk menambahkan batasan ke keempat arah sebagaimana diperlukan oleh tata letak Anda.

Bangun UI Responsif dengan ConstraintLayout

Selain itu, saat ini, PercentRelativeLayout telah ditinggalkan (lihat dokumentasi Android ).

Cristina De Rito
sumber
1

Inilah cara saya memecahkan masalah itu:

int pHeight =  picture.getHeight();
int pWidth = picture.getWidth();
int vWidth = preview.getWidth();
preview.getLayoutParams().height = (int)(vWidth*((double)pHeight/pWidth));

pratinjau - imageView dengan lebar disetel ke "match_parent" dan scaleType ke "cropCenter"

gambar - objek Bitmap untuk diatur dalam imageView src.

Itu bekerja cukup baik untuk saya.

udenfox
sumber
Anda belum menjelaskan di mana kode ini harus diletakkan. Anda juga belum menjelaskan mengapa Anda melakukannya = vw*ph/pwdaripada yang lebih sederhana = vw. (Saya pikir Anda melakukan ini untuk mempertahankan rasio aspek gambar sumber, daripada memaksakan pratinjau segi empat.)
ToolmakerSteve
0

Saya tidak berpikir ada cara Anda bisa melakukannya dalam file layout XML, dan saya tidak berpikir android:scaleTypeatribut akan berfungsi seperti yang Anda inginkan.
Satu-satunya cara adalah melakukannya secara terprogram. Anda dapat mengatur lebar menjadi fill_parent dan dapat menggunakan lebar layar sebagai ketinggian metode Viewatau dapat menggunakan View.getWidth().

cupu
sumber
0

Fungsi ImageView "scaleType" dapat membantu Anda di sini.

Kode ini akan menjaga rasio aspek dan menempatkan gambar di atas:

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitStart"

Berikut ini adalah pos yang bagus yang menunjukkan kemungkinan dan penampilan dari menggunakan scaleType.

Sampel ImageType scaleType

ac_banks
sumber
"scaleType" tidak membantu di sini. Tujuannya agar ImageView sendiri selalu berbentuk persegi, bukan hanya gambar di dalamnya. Dengan scaleType, ImageView mungkin lebih besar dari gambar.
ToolmakerSteve
0

saya suka ini -

layout.setMinimumHeight(layout.getWidth());
HarshitG
sumber