Ajustar la imagen en ImageView, mantener la relación de aspecto y luego cambiar el tamaño de ImageView a las dimensiones de la imagen?

¿Cómo adaptar una imagen de tamaño aleatorio a un ImageView ?
Cuando:

  • Inicialmente las dimensiones de ImageView son 250dp * 250dp
  • La dimensión más grande de la imagen debe ampliarse / reducirse a 250dp
  • La imagen debe mantener su relación de aspecto
  • Las dimensiones de ImageView deben coincidir con las dimensiones de la imagen escalada después de escalar

Por ejemplo, para una imagen de 100 * 150, la imagen y el ImageView deben ser 166 * 250.
Por ejemplo, para una imagen de 150 * 100, la imagen y el ImageView deben ser 250 * 166.

Si configuro los límites como

  

las imágenes se ajustan correctamente en ImageView , pero ImageView siempre es 250dp * 250dp.

    (La respuesta fue muy modificada después de las aclaraciones a la pregunta original)

    Después de aclaraciones:
    Esto no se puede hacer solo en xml . No es posible escalar tanto la imagen como el ImageView para que la única dimensión de la imagen sea siempre de 250dp y el ImageView tenga las mismas dimensiones que la imagen.

    Este código escala Drawable de un ImageView para permanecer en un cuadrado como 250dp x 250dp con una dimensión exactamente 250dp y manteniendo la relación de aspecto. Luego, ImageView se redimensiona para que coincida con las dimensiones de la imagen escalada. El código se usa en una actividad. Lo probé a través de un clic en el controlador de clic.

    Disfrutar. 🙂

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

    El código xml para ImageView :

      

    Gracias a esta discusión para el código de escala:
    http://www.anddev.org/resize_and_rotate_image_-_example-t621.html

    ACTUALIZACIÓN 7 de noviembre de 2012:
    Se agregó una verificación del puntero nulo como se sugiere en los comentarios

    Puede que no responda a esta pregunta específica, pero si alguien, como yo, busca una respuesta sobre cómo ajustar la imagen en ImageView con un tamaño limitado (por ejemplo, maxWidth ) mientras conserva la relación de aspecto y luego elimina el exceso de espacio ocupado por ImageView. entonces la solución más simple es usar las siguientes propiedades en XML:

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

    El código Abajo hace que el bitmap se ajuste perfectamente al mismo tamaño de la vista de la imagen. Obtenga la altura y el ancho de la imagen de bitmap y luego calcule la nueva altura y ancho con la ayuda de los parámetros de la vista de imagen. Eso le da la imagen requerida con la mejor relación de aspecto.

     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) 

    disfrutar.

    intente agregar android:scaleType="fitXY" a su ImageView .

    Después de buscar un día, creo que esta es la solución más fácil:

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

    La mejor solución que funciona en la mayoría de los casos es

    Aquí hay un ejemplo:

      

    todo esto se puede hacer usando XML … los otros métodos parecen bastante complicados. De todos modos, simplemente establece la altura en lo que quieras en dp, luego configura el ancho para ajustar el contenido o viceversa. Use scaleType fitCenter para ajustar el tamaño de la imagen.

      

    Editado Jarno Argillanders respuesta:

    Cómo ajustar la imagen con su ancho y alto:

    1) Inicializa ImageView y establece Imagen:

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

    2) Ahora cambie el tamaño:

     scaleImage(iv); 

    Método de scaleImage editado: ( puede reemplazar valores de límite ESPERADOS )

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

    Y .xml:

      

    Usa este código:

      

    Esto lo hizo por mi caso.

       

    Necesitaba hacer esto en un diseño restringido con Picasso, así que reuní algunas de las respuestas anteriores y obtuve esta solución (ya sé la relación de aspecto de la imagen que estoy cargando, así que eso ayuda):

    Invocado en mi código de actividad en algún lugar después de 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... } } 

    En mi XML

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

    Tenga en cuenta la falta de un atributo constraintBottom_toBottomOf. ImageLoader es mi propia clase estática para los métodos y constantes de carga de imágenes.

    Necesitaba tener un ImageView y un bitmap, por lo que el bitmap se escala a tamaño de ImageView, y el tamaño de ImageView es el mismo del bitmap escalado :).

    Estaba mirando esta publicación para saber cómo hacerlo, y finalmente hice lo que quería, aunque no del modo descrito aquí.

       

    y luego en el método 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; } 

    y luego el código 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); } 

    Y el resultado es que la imagen encaja perfectamente en el interior, manteniendo la relación de aspecto, y no tiene píxeles sobrantes adicionales de ImageView cuando el bitmap está dentro.

    Resultado

    Es importante que ImageView tenga wrap_content y adjustViewBounds en true, luego setMaxWidth y setMaxHeight funcionarán, esto está escrito en el código fuente de 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. */