Adatta l'immagine a ImageView, mantieni le proporzioni e ridimensiona ImageView alle dimensioni dell'immagine?


165

Come adattare un'immagine di dimensioni casuali a una ImageView?
Quando:

  • inizialmente ImageView dimensioni sono 250dp * 250dp
  • La dimensione più grande dell'immagine dovrebbe essere ridimensionata su / giù a 250dp
  • L'immagine dovrebbe mantenere le proporzioni
  • Le ImageViewdimensioni devono corrispondere alle dimensioni dell'immagine ridimensionata dopo il ridimensionamento

Ad esempio, per un'immagine di 100 * 150, l'immagine e la ImageViewdovrebbero essere 166 * 250.
Ad esempio, per un'immagine di 150 * 100, l'immagine e la ImageViewdovrebbero essere 250 * 166.

Se imposto i limiti come

<ImageView
    android:id="@+id/picture"
    android:layout_width="250dp"
    android:layout_height="250dp"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:adjustViewBounds="true" />

le immagini si adattano correttamente a ImageView, ma ImageViewè sempre 250dp * 250dp.


Uh, intendi cambiare la dimensione della ImageViewdimensione dell'immagine? Ad esempio un'immagine di 100dp x 150dp si ridimensionerebbe ImageViewcon le stesse misure? O vuoi dire come ridimensionare l'immagine ai ImageViewlimiti. Ad esempio, l'immagine di 1000 dpi x 875 dpi verrebbe ridimensionata in 250 dpi x 250 dpi. Devi mantenere le proporzioni?
Jarno Argillander,

Voglio che ImageView abbia le dimensioni dell'immagine e che l'immagine abbia la sua dimensione maggiore sia uguale a 250dp e mantenga le proporzioni. Ad esempio, per un'immagine di 100 * 150, voglio che l'immagine e ImageView siano 166 * 250. Aggiornerò la mia domanda.
lug

Vuoi fare il ridimensionamento / regolazione solo quando visualizzi un'attività (esegui una volta) o quando fai qualcosa sull'attività come selezionare un'immagine dalla galleria / web (fai molte volte ma non sotto carico) o entrambi?
Jarno Argillander,

Vedi la mia risposta modificata, che dovrebbe fare esattamente come lo desideravi :)
Jarno Argillander,

Risposte:


138

(La risposta è stata fortemente modificata dopo chiarimenti alla domanda originale)

Dopo chiarimenti:
questo non può essere fatto solo in XML . Non è possibile ridimensionare sia l'immagine ImageViewche la dimensione unica dell'immagine sarebbe sempre 250dp e ImageViewavrebbe le stesse dimensioni dell'immagine.

Questo codice scale Drawable di un ImageViewdi rimanere in una piazza come 250dp x 250dp con una dimensione esattamente 250dp e mantenendo le proporzioni. Quindi ImageViewviene ridimensionato per adattarsi alle dimensioni dell'immagine ridimensionata. Il codice viene utilizzato in un'attività. L'ho provato tramite il gestore di clic sui pulsanti.

Godere. :)

private void scaleImage(ImageView view) throws NoSuchElementException  {
    // Get bitmap from the the ImageView.
    Bitmap bitmap = null;

    try {
        Drawable drawing = view.getDrawable();
        bitmap = ((BitmapDrawable) drawing).getBitmap();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("No drawable on given view");
    } catch (ClassCastException e) {
        // Check bitmap is Ion drawable
        bitmap = Ion.with(view).getBitmap();
    }

    // Get current dimensions AND the desired bounding box
    int width = 0;

    try {
        width = bitmap.getWidth();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("Can't find bitmap on given view/drawable");
    }

    int height = bitmap.getHeight();
    int bounding = dpToPx(250);
    Log.i("Test", "original width = " + Integer.toString(width));
    Log.i("Test", "original height = " + Integer.toString(height));
    Log.i("Test", "bounding = " + Integer.toString(bounding));

    // Determine how much to scale: the dimension requiring less scaling is
    // closer to the its side. This way the image always stays inside your
    // bounding box AND either x/y axis touches it.  
    float xScale = ((float) bounding) / width;
    float yScale = ((float) bounding) / height;
    float scale = (xScale <= yScale) ? xScale : yScale;
    Log.i("Test", "xScale = " + Float.toString(xScale));
    Log.i("Test", "yScale = " + Float.toString(yScale));
    Log.i("Test", "scale = " + Float.toString(scale));

    // Create a matrix for the scaling and add the scaling data
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);

    // Create a new bitmap and convert it to a format understood by the ImageView 
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth(); // re-use
    height = scaledBitmap.getHeight(); // re-use
    BitmapDrawable result = new BitmapDrawable(scaledBitmap);
    Log.i("Test", "scaled width = " + Integer.toString(width));
    Log.i("Test", "scaled height = " + Integer.toString(height));

    // Apply the scaled bitmap
    view.setImageDrawable(result);

    // Now change ImageView's dimensions to match the scaled image
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);

    Log.i("Test", "done");
}

private int dpToPx(int dp) {
    float density = getApplicationContext().getResources().getDisplayMetrics().density;
    return Math.round((float)dp * density);
}

Il codice XML per ImageView:

<ImageView a:id="@+id/image_box"
    a:background="#ff0000"
    a:src="@drawable/star"
    a:layout_width="wrap_content"
    a:layout_height="wrap_content"
    a:layout_marginTop="20dp"
    a:layout_gravity="center_horizontal"/>


Grazie a questa discussione per il codice di ridimensionamento:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html


AGGIORNAMENTO 7 novembre 2012:
Aggiunto controllo puntatore null come suggerito nei commenti


1
ImageView sarà sempre 250 * 250.
lug

2
Ok. Questo non può essere fatto solo in XML. È richiesto il codice Java. Con xml puoi ridimensionare l'immagine o il ImageView, non entrambi.
Jarno Argillander,

94
non avevo capito che potevi sostituire Android: con un:
StackOverflowed

2
Ion è un framework per il networking asincrono e il caricamento delle immagini: github.com/koush/ion
Thomas

1
Java è un linguaggio estremamente brutto perché richiede di scrivere così tanto codice per compiti così semplici.
Dmitry,

246

Potrebbe non essere una risposta a questa domanda specifica, ma se qualcuno, come me, sta cercando una risposta per adattare l'immagine in ImageView con dimensioni limitate (ad esempio, maxWidth) preservando le proporzioni e quindi liberarsi dello spazio eccessivo occupato da ImageView, quindi la soluzione più semplice è utilizzare le seguenti proprietà in XML:

    android:scaleType="centerInside"
    android:adjustViewBounds="true"

14
Funziona se non vuoi che l'immagine venga ingrandita se è troppo piccola.
Janusz,

come posso ridimensionarlo se è troppo piccolo e anche mantenere le proporzioni?
Kaustubh Bhagwat,

se qualcuno ne ha bisogno, "fitCenter" è un altro attributo per scaleType e non ridimensionerà l'immagine, ma per qualsiasi immagine grande, si adatterà alla dimensione massima dell'immagine all'interno della casella di visualizzazione mantenendo le proporzioni
yogesh prajapati

per ridimensionare le immagini di piccole dimensioni utilizzare invece scaleType = "centerCrop".
Eaweb,

un'altra cosa per me lavorare con questa soluzione è usare "android: src" e non "android: background" per rifare la mia immagine.
Codingpan

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

23

Il codice sottostante rende la bitmap perfettamente con le stesse dimensioni della visualizzazione dell'immagine. Ottieni l'altezza e la larghezza dell'immagine bitmap e quindi calcola la nuova altezza e larghezza con l'aiuto dei parametri di imageview. Che ti dà l'immagine richiesta con le migliori proporzioni.

int currentBitmapWidth = bitMap.getWidth();
int currentBitmapHeight = bitMap.getHeight();

int ivWidth = imageView.getWidth();
int ivHeight = imageView.getHeight();
int newWidth = ivWidth;

newHeight = (int) Math.floor((double) currentBitmapHeight *( (double) new_width / (double) currentBitmapWidth));

Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap, newWidth, newHeight, true);

imageView.setImageBitmap(newbitMap)

godere.


3
Ciò ridurrà semplicemente l'altezza originale dello stesso fattore con cui è stata ridotta la larghezza. Questo non garantisce che newHeight <ivHeight. Idealmente dovresti controllare quale rapporto è più grande (currentBitmapHeight / ivHeight, currentBitmapWidth / ivWidth) e quindi sulla base di questo prendere ulteriori decisioni.
Sumit Trehan,

1
In realtà funziona alla perfezione, anche se non hai bisogno di ivHeight o newWidth, inserisci invece ivWidth nel calcolo.
Stuart

14

prova ad aggiungere android:scaleType="fitXY"al tuo ImageView.


5
Ciò modificherà le proporzioni se l'immagine originale non è quadrata.
lug

1
fitXYcambierà quasi sempre le proporzioni dell'immagine. OP indica chiaramente che le proporzioni DEVONO essere mantenute.
IcyFlame il

7

Dopo aver cercato un giorno, penso che questa sia la soluzione più semplice:

imageView.getLayoutParams().width = 250;
imageView.getLayoutParams().height = 250;
imageView.setAdjustViewBounds(true);

2
Grazie per la tua bella risposta, ma penso che sia meglio aggiungere adjustViewBoundsa XML

7

La migliore soluzione che funziona nella maggior parte dei casi è

Ecco un esempio:

<ImageView android:id="@+id/avatar"
           android:layout_width="match_parent"
           android:layout_height="match_parent"
           android:scaleType="fitXY"/>

1
Non fare affidamento su API obsolete (fill_parent)
fdermishin,

come risponde alla domanda di OP. Questo non manterrà il rapporto aspet
Alex

6

tutto ciò può essere fatto usando XML ... gli altri metodi sembrano piuttosto complicati. Ad ogni modo, basta impostare l'altezza su ciò che si desidera in dp, quindi impostare la larghezza per avvolgere il contenuto o viceversa. Utilizzare scaleType fitCenter per regolare le dimensioni dell'immagine.

<ImageView
    android:layout_height="200dp"
    android:layout_width="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"
    android:src="@mipmap/ic_launcher"
    android:layout_below="@+id/title"
    android:layout_margin="5dip"
    android:id="@+id/imageView1">

4

Usa questo codice:

<ImageView android:id="@+id/avatar"
           android:layout_width="fill_parent"
           android:layout_height="match_parent"
           android:scaleType="fitXY" />

4

Modificato Jarno Argillanders risponde:

Come adattare l'immagine alla larghezza e all'altezza:

1) Inizializza ImageView e imposta l'immagine:

iv = (ImageView) findViewById(R.id.iv_image);
iv.setImageBitmap(image);

2) Ora ridimensiona:

scaleImage(iv);

scaleImageMetodo modificato : ( è possibile sostituire i valori di delimitazione ATTESI )

private void scaleImage(ImageView view) {
    Drawable drawing = view.getDrawable();
    if (drawing == null) {
        return;
    }
    Bitmap bitmap = ((BitmapDrawable) drawing).getBitmap();

    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int xBounding = ((View) view.getParent()).getWidth();//EXPECTED WIDTH
    int yBounding = ((View) view.getParent()).getHeight();//EXPECTED HEIGHT

    float xScale = ((float) xBounding) / width;
    float yScale = ((float) yBounding) / height;

    Matrix matrix = new Matrix();
    matrix.postScale(xScale, yScale);

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

    view.setImageDrawable(result);

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

E .xml:

<ImageView
    android:id="@+id/iv_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal" />

Penso che questo cast: LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams (); dovrebbe andare dall'altra parte, poiché MarginLayoutParams eredita da ViewGroup.LayoutParams.
Jay Jacobs,

3

Questo è stato per il mio caso.

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

2

se non funziona per te, sostituisci android: background con android: src

android: src giocherà il trucco principale

    <ImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitCenter"
    android:src="@drawable/bg_hc" />

funziona benissimo come un fascino

inserisci qui la descrizione dell'immagine


1

Avevo bisogno di avere un ImageView e un Bitmap, quindi il Bitmap è ridimensionato in base alle dimensioni di ImageView e le dimensioni di ImageView sono le stesse del Bitmap in scala :).

Stavo cercando in questo post come farlo, e alla fine ho fatto quello che volevo, non nel modo descritto qui.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/acpt_frag_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/imageBackground"
android:orientation="vertical">

<ImageView
    android:id="@+id/acpt_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:adjustViewBounds="true"
    android:layout_margin="@dimen/document_editor_image_margin"
    android:background="@color/imageBackground"
    android:elevation="@dimen/document_image_elevation" />

e quindi nel metodo onCreateView

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_scanner_acpt, null);

    progress = view.findViewById(R.id.progress);

    imageView = view.findViewById(R.id.acpt_image);
    imageView.setImageBitmap( bitmap );

    imageView.getViewTreeObserver().addOnGlobalLayoutListener(()->
        layoutImageView()
    );

    return view;
}

e quindi il codice layoutImageView ()

private void layoutImageView(){

    float[] matrixv = new float[ 9 ];

    imageView.getImageMatrix().getValues(matrixv);

    int w = (int) ( matrixv[Matrix.MSCALE_X] * bitmap.getWidth() );
    int h = (int) ( matrixv[Matrix.MSCALE_Y] * bitmap.getHeight() );

    imageView.setMaxHeight(h);
    imageView.setMaxWidth(w);

}

E il risultato è che l'immagine si adatta perfettamente all'interno, mantenendo le proporzioni e non ha pixel rimanenti extra da ImageView quando Bitmap è all'interno.

Risultato

È importante ImageView avere wrap_content e regolareViewBounds su true, quindi setMaxWidth e setMaxHeight funzioneranno, questo è scritto nel codice sorgente di ImageView,

/*An optional argument to supply a maximum height for this view. Only valid if
 * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a
 * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
 * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
 * layout params to WRAP_CONTENT. */

0

Avevo bisogno di farlo in un layout di vincolo con Picasso, quindi ho messo insieme alcune delle risposte di cui sopra e ho trovato questa soluzione (Conosco già le proporzioni dell'immagine che sto caricando, quindi aiuta):

Chiamato nel mio codice attività da qualche parte dopo setContentView (...)

protected void setBoxshotBackgroundImage() {
    ImageView backgroundImageView = (ImageView) findViewById(R.id.background_image_view);

    if(backgroundImageView != null) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int width = displayMetrics.widthPixels;
        int height = (int) Math.round(width * ImageLoader.BOXART_HEIGHT_ASPECT_RATIO);

        // we adjust the height of this element, as the width is already pinned to the parent in xml
        backgroundImageView.getLayoutParams().height = height;

        // implement your Picasso loading code here
    } else {
        // fallback if no element in layout...
    }
}

Nel mio XML

<?xml version="1.0" encoding="utf-8"?>

<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="0dp">

    <ImageView
        android:id="@+id/background_image_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="fitStart"
        app:srcCompat="@color/background"
        android:adjustViewBounds="true"
        tools:layout_editor_absoluteY="0dp"
        android:layout_marginTop="0dp"
        android:layout_marginBottom="0dp"
        android:layout_marginRight="0dp"
        android:layout_marginLeft="0dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <!-- other elements of this layout here... -->

</android.support.constraint.ConstraintLayout>

Si noti la mancanza di un attributo restringBottom_toBottomOf. ImageLoader è la mia classe statica per i metodi e le costanti di caricamento delle immagini.


0

Sto usando una soluzione molto semplice. Ecco il mio codice:

imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.getLayoutParams().height = imageView.getLayoutParams().width;
imageView.setMinimumHeight(imageView.getLayoutParams().width);

Le mie foto vengono aggiunte dinamicamente in una visualizzazione griglia. Quando si effettuano queste impostazioni per la visualizzazione dell'immagine, l'immagine può essere visualizzata automaticamente in rapporto 1: 1.


0

Usa la matematica semplice per ridimensionare l'immagine. puoi ridimensionare ImageViewo ridimensionare l'immagine disegnabile di quella impostata ImageView. trova la larghezza e l'altezza della tua bitmap su cui vuoi impostare ImageViewe chiama il metodo desiderato. supponiamo che la tua larghezza 500 sia maggiore dell'altezza del metodo call

//250 is the width you want after resize bitmap
Bitmat bmp = BitmapScaler.scaleToFitWidth(bitmap, 250) ;
ImageView image = (ImageView) findViewById(R.id.picture);
image.setImageBitmap(bmp);

Utilizzare questa classe per ridimensionare bitmap.

public class BitmapScaler{
// Scale and maintain aspect ratio given a desired width
// BitmapScaler.scaleToFitWidth(bitmap, 100);
 public static Bitmap scaleToFitWidth(Bitmap b, int width)
  {
    float factor = width / (float) b.getWidth();
    return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
  }


  // Scale and maintain aspect ratio given a desired height
  // BitmapScaler.scaleToFitHeight(bitmap, 100);
  public static Bitmap scaleToFitHeight(Bitmap b, int height)
  {
    float factor = height / (float) b.getHeight();
    return Bitmap.createScaledBitmap(b, (int) (b.getWidth() * factor), height, true);
   }
 }

codice xml è

<ImageView
android:id="@+id/picture"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:adjustViewBounds="true"
android:scaleType="fitcenter" />

0

Risposta rapida:

<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" />
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.