webentwicklung-frage-antwort-db.com.de

Bild in ImageView einpassen, Seitenverhältnis beibehalten und dann ImageView an Bildmaße anpassen?

Wie passt man ein Bild von zufälliger Größe an ein ImageView an?
Wann:

  • Anfänglich ImageView-Abmessungen sind 250dp * 250dp
  • Die größere Dimension des Bildes sollte auf 250dp skaliert werden
  • Das Bild sollte das Seitenverhältnis beibehalten
  • Die ImageView-Dimensionen sollten nach der Skalierung mit den Abmessungen des skalierten Bildes übereinstimmen

Z.B. Bei einem Bild von 100 * 150 sollten das Bild und das _ImageView 166 * 250 sein.
Z.B. Für ein Bild von 150 * 100 sollten das Bild und das ImageView 250 * 166 sein. 

Wenn ich die Grenzen als setze

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

bilder passen richtig in ImageView, aber ImageView ist immer 250dp * 250dp.

143
jul

(Die Antwort wurde stark geändert, nachdem die ursprüngliche Frage präzisiert wurde)}

Nach Klärung:
Dieses kann nicht nur in xml ausgeführt werden. Es ist nicht möglich, das Bild und das ImageView so zu skalieren, dass die eine Dimension des Bildes immer 250 dp beträgt und das ImageView die gleichen Abmessungen wie das Bild hat.

Dieser Code skaliertDrawable eines ImageView, um in einem Quadrat wie 250dp x 250dp mit einer Dimension genau 250dp zu bleiben und das Seitenverhältnis beizubehalten. Dann wird ImageView so angepasst, dass es den Abmessungen des skalierten Bildes entspricht. Der Code wird in einer Aktivität verwendet. Ich habe es per Button-Click-Handler getestet.

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

Der XML-Code für 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"/>


Dank dieser Diskussion für den Skalierungscode:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html


7. UPDATE, November 2012:
Die Nullzeigerprüfung wurde hinzugefügt, wie in den Kommentaren vorgeschlagen

131

Kann für diese spezifische Frage keine Antwort sein, aber wenn jemand wie ich nach einer Antwort sucht, wie ein Bild in ImageView mit einer begrenzten Größe (z. B. maxWidth) angepasst werden soll, während das Seitenverhältnis beibehalten wird, und dann der übermäßige Bildbereich, der von ImageView belegt wird, entfernt wird, Die einfachste Lösung besteht darin, die folgenden Eigenschaften in XML zu verwenden:

    Android:scaleType="centerInside"
    Android:adjustViewBounds="true"
201
Sarge Borsch
<ImageView Android:layout_width="match_parent"
           Android:layout_height="wrap_content"
           Android:scaleType="centerCrop"
           Android:adjustViewBounds="true"/>
35
diesel

Mit dem folgenden Code wird die Bitmap mit derselben Größe der Bildansicht perfekt erstellt. Rufen Sie die Bildhöhe und -breite der Bitmap ab und berechnen Sie die neue Höhe und Breite mithilfe der Parameter von imageview. Das gibt Ihnen das gewünschte Bild mit dem besten Seitenverhältnis. 

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)

genießen.

21
Naresh Sharma

versuchen Sie, Android:scaleType="fitXY" zu Ihrer ImageView hinzuzufügen.

11
DeeFour

Nach der Suche nach einem Tag denke ich, dass dies die einfachste Lösung ist:

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

Die beste Lösung, die in den meisten Fällen funktioniert, ist

Hier ist ein Beispiel:

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

Verwenden Sie diesen Code:

<ImageView Android:id="@+id/avatar"
           Android:layout_width="fill_parent"
           Android:layout_height="match_parent"
           Android:scaleType="fitXY" />
4
Abhay Anand

das alles kann mit XML gemacht werden ... die anderen Methoden scheinen ziemlich kompliziert zu sein. Sie legen die Höhe auf jeden beliebigen Wert in dp fest und legen dann die Breite fest, um den Inhalt einzuwickeln oder umgekehrt. Verwenden Sie scaleType fitCenter, um die Größe des Bildes anzupassen.

<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
Thunderstick

Bearbeitet Jarno Argillanders Antwort:

So passen Sie das Bild in Breite und Höhe an:

1) ImageView initialisieren und Image einstellen:

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

2) Jetzt die Größe ändern:

scaleImage(iv);

Editierte scaleImage-Methode: (Sie können EXPECTED-Begrenzungswerte ersetzen)

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

Und .xml:

<ImageView
    Android:id="@+id/iv_image"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_gravity="center_horizontal" />
4
Volodymyr Kulyk

Das hat es für meinen Fall getan.

             <ImageView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_centerHorizontal="true"
                Android:scaleType="centerCrop"
                Android:adjustViewBounds="true"
                />
3
Ronny Kibet

Ich brauchte eine ImageView und eine Bitmap, daher ist die Bitmap auf die ImageView-Größe skaliert und die Größe der ImageView stimmt mit der skalierten Bitmap überein :).

Ich habe in diesem Beitrag nach dem Weg gesucht und schließlich getan, was ich will, nicht wie hier beschrieben.

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

und dann in der onCreateView-Methode

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

und dann layoutImageView () code

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

}

Und das Ergebnis ist, dass das Bild perfekt in das Bild passt und das Seitenverhältnis beibehalten..... Wenn die Bitmap im Inneren ist, werden in ImageView keine zusätzlichen Pixel übrig bleiben.

Ergebnis

ImageView muss unbedingt über Wrap_content und adjustViewBounds auf true verfügen. SetMaxWidth und setMaxHeight funktionieren, dies ist im Quelltext von ImageView geschrieben 

/*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. */
1
alekshandru

Verwenden Sie einfache Mathematik, um die Größe des Bildes zu ändern. Entweder können Sie die Größe von ImageView ändern, oder Sie können die Größe des zu zeichnenden Bildes ändern, als in ImageView festgelegt. Suchen Sie die Breite und Höhe Ihrer Bitmap, die Sie für ImageView festlegen möchten, und rufen Sie die gewünschte Methode auf. Angenommen, Ihre Breite 500 ist größer als die Höhe als die Aufrufmethode

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

Mit dieser Klasse können Sie die Größe von Bitmaps ändern.

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

xml code is

<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
Ritesh Namdev

Ich musste dies in einem Constraint-Layout mit Picasso erledigen, also habe ich einige der obigen Antworten zusammengestellt und diese Lösung gefunden (ich kenne bereits das Seitenverhältnis des Bildes, das ich lade, und das hilft)

In meinem Aktivitätscode irgendwo nach setContentView (...) aufgerufen

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...
    }
}

In meinem 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>

Beachten Sie das Fehlen eines constraintBottom_toBottomOf-Attributs. ImageLoader ist meine eigene statische Klasse für das Laden von Bildern mit Methoden und Konstanten.

0
the_dude_abides

Ich benutze eine sehr einfache Lösung. Hier mein 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);

Meine Bilder werden dynamisch in einer Rasteransicht hinzugefügt. Wenn Sie diese Einstellungen in der Bildansicht vornehmen, kann das Bild automatisch im Verhältnis 1: 1 angezeigt werden.

0
Bilal Demir