200 votes

Adapter l'image à l'ImageView, conserver le rapport d'aspect, puis redimensionner l'ImageView aux dimensions de l'image ?

Comment faire correspondre une image de taille aléatoire à une ImageView ?
Quand :

  • Initialement ImageView Les dimensions sont de 250dp * 250dp
  • La plus grande dimension de l'image doit être mise à l'échelle (250dp).
  • L'image doit conserver son rapport d'aspect
  • El ImageView les dimensions doivent correspondre aux dimensions de l'image après mise à l'échelle

Par exemple, pour une image de 100*150, l'image et les ImageView devrait être de 166*250.
Par exemple, pour une image de 150*100, l'image et les ImageView devrait être de 250*166.

Si je fixe les limites comme

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

les images s'insèrent correctement dans le ImageView mais le ImageView est toujours de 250dp * 250dp.

0 votes

Euh, voulez-vous dire pour changer la taille de la ImageView à la taille de l'image ? Par exemple, une image de 100 dp x 150 dp serait mise à l'échelle. ImageView aux mêmes mesures ? Ou voulez-vous dire comment mettre à l'échelle l'image aux ImageView limites. Par exemple, une image de 1000dp x 875dp sera mise à l'échelle en 250dp x 250dp. Avez-vous besoin de maintenir le rapport d'aspect ?

0 votes

Je veux que l'ImageView ait les dimensions de l'image, que la plus grande dimension de l'image soit égale à 250dp et qu'elle conserve son rapport d'aspect. Par exemple, pour une image de 100*150, je veux que l'image et l'ImageView soient de 166*250. Je vais mettre à jour ma question.

0 votes

Souhaitez-vous effectuer une mise à l'échelle/un ajustement uniquement lors de l'affichage d'une activité (à faire une fois) ou lors d'une action sur l'activité comme la sélection d'une image dans la galerie/le Web (à faire plusieurs fois mais pas au chargement) ou les deux ?

292voto

Sarge Borsch Points 2044

Ce n'est peut-être pas la réponse à cette question spécifique, mais si quelqu'un est, comme moi, à la recherche d'une réponse pour faire tenir une image dans une ImageView avec une taille limitée (par exemple, maxWidth ) tout en préservant l'Aspect Ratio et ensuite se débarrasser de l'espace excessif occupé par ImageView, alors la solution la plus simple est d'utiliser les propriétés suivantes dans le XML :

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

15 votes

Cela fonctionne si vous ne voulez pas que l'image soit redimensionnée si elle est trop petite.

0 votes

Comment puis-je l'agrandir si elle est trop petite tout en conservant le rapport d'aspect ?

1 votes

Si quelqu'un a besoin, "fitCenter" est un autre attribut pour scaleType, et il n'agrandira pas l'image, mais pour toute grande image, il adaptera la taille maximale de l'image à l'intérieur de la boîte de vue en maintenant le rapport d'aspect.

148voto

Jarno Argillander Points 3233

(La réponse a été fortement modifiée après des clarifications de la question originale)

Après les clarifications :
Ce site ne peut pas être fait en xml seulement . Il n'est pas possible de mettre à l'échelle à la fois l'image et l'écran. ImageView de sorte que l'une des dimensions de l'image soit toujours de 250dp et que le ImageView aurait les mêmes dimensions que l'image.

Ce code met à l'échelle Drawable d'un ImageView pour rester dans un carré comme 250dp x 250dp avec une dimension exactement 250dp et en gardant le rapport d'aspect. Ensuite, le ImageView est redimensionnée pour correspondre aux dimensions de l'image mise à l'échelle. Le code est utilisé dans une activité. Je l'ai testé via le gestionnaire de clic de bouton.

Profitez-en. :)

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

Le code xml pour le 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"/>

Merci à cette discussion pour le code de mise à l'échelle :
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

MISE À JOUR du 7 novembre 2012 :
Ajout de la vérification des pointeurs nuls comme suggéré dans les commentaires

1 votes

L'ImageView sera toujours de 250*250.

2 votes

Ok. Cela ne peut pas être fait en xml seulement. Du code Java est nécessaire. Avec le xml, vous pouvez soit mettre à l'échelle l'image, soit la ImageView et non les deux.

119 votes

Je n'avais pas réalisé que l'on pouvait remplacer Android : par un :

55voto

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

0 votes

Ça marche du tonnerre ! Bien fait.

26voto

Naresh Sharma Points 1766

Le code ci-dessous rend le bitmap parfaitement avec la même taille de l'imageview. Obtenez la hauteur et la largeur de l'image bitmap, puis calculez la nouvelle hauteur et largeur à l'aide des paramètres de l'imageview. Cela vous donne l'image requise avec le meilleur ratio d'aspect.

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)

profiter.

3 votes

La hauteur d'origine sera ainsi réduite du même facteur que la largeur. Cela ne garantira pas que newHeight < ivHeight. Idéalement, vous devriez vérifier quel rapport est le plus grand (currentBitmapHeight /ivHeight , currentBitmapWidth /ivWidth ) et ensuite, sur la base de cela, prendre une autre décision.

1 votes

Cela fonctionne parfaitement, bien que vous n'ayez pas besoin de ivHeight ou de newWidth, mettez simplement ivWidth dans le calcul à la place.

16voto

DeeFour Points 67

Essayez d'ajouter android:scaleType="fitXY" à votre ImageView .

8 votes

Cela modifiera le rapport d'aspect si l'image originale n'est pas carrée.

1 votes

fitXY modifiera presque toujours le rapport hauteur/largeur de l'image. Le PO mentionne clairement que le rapport d'aspect DOIT être maintenu.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X