Comment adapter une image de taille aléatoire à une ImageView
?
Quand:
ImageView
sont 250dp * 250dpImageView
doivent correspondre aux dimensions de l'image mise à l'échelle après la mise à l'échellePar exemple. pour une image de 100 * 150, l'image et la ImageView
doivent être 166 * 250.
Par exemple. pour une image de 150 * 100, l'image et la ImageView
doivent être 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 tiennent correctement dans la ImageView
, mais la ImageView
est toujours de 250dp * 250dp.
(La réponse a été fortement modifiée après des éclaircissements sur la question initiale))
Après clarifications:
Ce ne peut pas être fait en XML seulement. Il n'est pas possible de redimensionner à la fois l'image et la ImageView
de sorte que la seule dimension de l'image soit toujours 250dp et que la ImageView
ait les mêmes dimensions que l'image.
Ce code met à l'échelleDrawable
d'une ImageView
pour rester dans un carré tel que 250dp x 250dp avec une dimension de 250dp exactement et en conservant les proportions. La ImageView
est ensuite redimensionnée pour correspondre aux dimensions de l'image redimensionnée. Le code est utilisé dans une activité. Je l'ai testé via un gestionnaire de clic sur le bouton.
Prendre plaisir. :)
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 la 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
UPDATE 7 novembre 2012:
Ajout d'une vérification du pointeur null comme suggéré dans les commentaires
Peut-être pas une réponse pour cette question spécifique, mais si quelqu'un, comme moi, cherche une réponse, comment ajuster une image dans ImageView avec une taille limitée (par exemple, maxWidth
) tout en préservant le rapport d'aspect, puis en éliminant l'espace excessif occupé par ImageView, la solution la plus simple consiste alors à utiliser les propriétés suivantes en XML:
Android:scaleType="centerInside"
Android:adjustViewBounds="true"
<ImageView Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:scaleType="centerCrop"
Android:adjustViewBounds="true"/>
Le code ci-dessous rend le bitmap parfaitement avec la même taille que la vue image. Obtenez la hauteur et la largeur de l'image bitmap, puis calculez la nouvelle hauteur et largeur à l'aide des paramètres de imageview. Cela vous donne l'image requise avec le meilleur rapport 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)
prendre plaisir.
essayez d’ajouter Android:scaleType="fitXY"
à votre ImageView
.
Après avoir cherché pendant une journée, je pense que c'est la solution la plus simple:
imageView.getLayoutParams().width = 250;
imageView.getLayoutParams().height = 250;
imageView.setAdjustViewBounds(true);
La meilleure solution qui fonctionne dans la plupart des cas est
Voici un exemple:
<ImageView Android:id="@+id/avatar"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:scaleType="fitXY"/>
Utilisez ce code:
<ImageView Android:id="@+id/avatar"
Android:layout_width="fill_parent"
Android:layout_height="match_parent"
Android:scaleType="fitXY" />
tout cela peut être fait en utilisant XML ... les autres méthodes semblent assez compliquées ... De toute façon, il vous suffit de définir la hauteur de votre choix dans dp, puis de définir la largeur pour envelopper le contenu ou vice-versa. Utilisez scaleType fitCenter pour ajuster la taille de l'image.
<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">
Édité Jarno Argillanders answer:
Comment adapter l’image à votre largeur et votre hauteur:
1) Initialiser ImageView et définir l'image:
iv = (ImageView) findViewById(R.id.iv_image);
iv.setImageBitmap(image);
2) maintenant redimensionner:
scaleImage(iv);
Méthode scaleImage
modifiée: (vous pouvez remplacer les valeurs englobantes EXPECTED)
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);
}
Et .xml:
<ImageView
Android:id="@+id/iv_image"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:layout_gravity="center_horizontal" />
Cela l'a fait pour mon cas.
<ImageView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:layout_centerHorizontal="true"
Android:scaleType="centerCrop"
Android:adjustViewBounds="true"
/>
J'avais besoin d'un ImageView et d'un bitmap, de sorte que le bitmap soit redimensionné à la taille d'ImageView et que sa taille soit identique à celle du bitmap redimensionné :).
Je cherchais dans ce billet comment faire et, finalement, j'ai fait ce que je voulais, mais pas de la manière décrite ici.
<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" />
puis dans la méthode 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;
}
puis code 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);
}
Et le résultat est que l'image s'intègre parfaitement à l'intérieur, tout en conservant le rapport de format, .__, et ne laisse pas de pixels supplémentaires laissés par ImageView lorsque le bitmap est à l'intérieur.
Il est important que ImageView ait Wrap_content et adjustViewBounds égal à true, Alors setMaxWidth et setMaxHeight fonctionneront, cela est écrit dans le code source 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. */
Utilisez Simple math pour redimensionner l'image. soit vous pouvez redimensionner ImageView
ou vous pouvez redimensionner une image dessinable par rapport à ImageView
. Recherchez la largeur et la hauteur de votre bitmap que vous souhaitez définir sur ImageView
et appelez la méthode souhaitée. supposons que votre largeur 500 soit supérieure à la hauteur de la méthode 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);
Vous utilisez cette classe pour redimensionner le 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);
}
}
le code XML est
<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" />
J'avais besoin de faire cela dans une mise en page de contraintes avec Picasso, alors j'ai rassemblé certaines des réponses ci-dessus et j'ai trouvé cette solution (je connais déjà le format de l'image que je charge, ce qui aide):
Appelé dans mon code d'activité quelque part après 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...
}
}
Dans mon 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>
Notez l'absence d'attribut constraintBottom_toBottomOf. ImageLoader est ma propre classe statique pour les méthodes et les constantes d'utilisation de chargement d'image.
J'utilise une solution très simple. Voici mon code:
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);
Mes images sont ajoutées dynamiquement dans un gridview. Lorsque vous définissez ces paramètres dans la visualisation d'image, l'image peut être automatiquement affichée au format 1: 1.