So skalieren Sie ein Bild in ImageView, um das Seitenverhältnis beizubehalten

526

In Android, definierte ich eine ImageView‚s layout_widthzu sein fill_parent(was die gesamte Breite des Telefons aufgreift).

Wenn das Bild, das ich eingefügt habe, ImageViewgrößer als das ist layout_width, wird es von Android skaliert, oder? Aber was ist mit der Höhe? Wenn Android das Bild skaliert, bleibt das Seitenverhältnis erhalten?

Was ich herausfinde, ist, dass es oben und unten einen Leerraum gibt, ImageViewwenn Android ein Bild skaliert, das größer als das ist ImageView. Ist das wahr? Wenn ja, wie kann ich diesen Leerraum entfernen?

Michael
quelle

Antworten:

799
  1. Ja, standardmäßig verkleinert Android Ihr Bild, um es an die ImageView anzupassen, wobei das Seitenverhältnis beibehalten wird. Stellen Sie jedoch sicher, dass Sie das Bild mit android:src="..."anstatt auf ImageView einstellen android:background="...". src=Hiermit wird das Bild skaliert, wobei das Seitenverhältnis beibehalten wird. Das Bild wird jedoch background=skaliert und verzerrt, damit es genau an die Größe der ImageView angepasst wird. (Sie können jedoch gleichzeitig einen Hintergrund und eine Quelle verwenden. Dies kann hilfreich sein, wenn Sie beispielsweise mit nur einer ImageView einen Rahmen um das Hauptbild anzeigen möchten.)

  2. Sie sollten auch sehen android:adjustViewBounds, dass sich die Größe der ImageView an das neu skalierte Bild anpasst. Wenn Sie beispielsweise ein rechteckiges Bild in einer normalerweise quadratischen ImageView haben, wird durch Anpassen von ViewVounds = true die Größe der ImageView ebenfalls auf rechteckig geändert. Dies wirkt sich dann darauf aus, wie andere Ansichten in der ImageView angeordnet sind.

    Dann können Sie, wie Samuh schrieb, die Art und Weise ändern, wie Bilder standardmäßig skaliert werden, indem Sie den android:scaleTypeParameter verwenden. Der einfachste Weg, um herauszufinden, wie das funktioniert, wäre übrigens gewesen, selbst ein bisschen zu experimentieren! Denken Sie daran, die Layouts im Emulator selbst (oder auf einem tatsächlichen Telefon) zu betrachten, da die Vorschau in Eclipse normalerweise falsch ist.

Steve Haley
quelle
18
Das ist das Gleiche, nur in Code anstatt in XML. setImageBitmapist das gleiche wie android:src="..."und setBackground...istandroid:background="..."
Steve Haley
4
@ SuperUser image.setImageDrawable(...)ist auch android:src="..."in XML.
PureSpider
11
"android: adjustViewBounds" ist hier praktisch! Wenn Sie dies nicht hinzufügen, treten höchstwahrscheinlich Probleme mit der nicht korrekten Skalierung von ImageView-Rahmen / -Begrenzungen / -Containern auf.
Wütend 84
2
src = vs background = war der Unterschied für mich!
Christopher Rathgeb
21
android:adjustViewBoundswar das letzte Stück zu meinem Puzzle, danke!
themarketka
281

Siehe android:adjustViewBounds.

Setzen Sie dies auf true, wenn Sie möchten, dass ImageView seine Grenzen anpasst, um das Seitenverhältnis des Zeichnungsobjekts beizubehalten.

Gratzi
quelle
6
Dies ist die richtige Lösung für das Problem. Wir hatten dies in unserer Bildansicht, in der die Höhe all diese zusätzlichen Leerzeichen enthielt. Es sind keine "transparenten Pixel", da wir fill_parent für width und wrap_content für height hatten. Wenn Sie nicht adjustViewBounds = true haben, erhalten Sie das zusätzliche Leerzeichen. Nachdem wir dies auf true gesetzt hatten, verschwand unser Problem. Vielen Dank!
Christophercotton
3
danke, das und das Setzen auf src anstelle von Hintergrund hat perfekt funktioniert!
Cameron
1
Dies ist die perfekte Lösung für das Problem. Verwenden Sie auch für die Größen den übergeordneten Container, um die Größe festzulegen, und legen Sie match_parent in der ImageView fest. Dies löst viele Probleme.
Nimila Hiranya
+1 für den Punkt. Ich schrieb das anfangs in einer "umgangssprachlicheren" Formulierung und hinderte mich daran, es einzureichen. Anstatt Federn zu kräuseln, ging ein PC.
Jacksonkr
168

An alle anderen, die dieses spezielle Problem haben. Sie haben eine ImageView, deren Breite fill_parentund Höhe proportional skaliert werden sollen:

Fügen Sie diese beiden Attribute hinzu ImageView:

android:adjustViewBounds="true"
android:scaleType="centerCrop"

Und stellen Sie die ImageViewBreite fill_parentund Höhe auf ein wrap_content.

Wenn Sie nicht möchten, dass Ihr Bild zugeschnitten wird, versuchen Sie Folgendes:

 android:adjustViewBounds="true"
 android:layout_centerInParent="true"
Kevin Parker
quelle
16
Ja, aber Ihr Bild wird zugeschnitten. Die perfekte Lösung würde sich auf die Breite dehnen, das Seitenverhältnis beibehalten und nicht beschneiden. Ich habe keine Ahnung, warum dies so schwierig sein muss ...
Warpzit
1
Ich auch :( Entschuldigung, wenn meine Lösung Ihnen nicht geholfen hat, aber sie hat mir geholfen.
Kevin Parker
2
Kevin, was du gesagt hast, war genau das, wonach ich gesucht habe. Wenn die Größe des Bildes kleiner als die des Bildschirms ist, wird es vergrößert und zentriert, perfekt. Vielen Dank.
Soham
1
+1, außer "(oder andere View)". AFAICT hat keine andere Ansicht adjustViewBoundsoder scaleTypeAttribute.
LarsH
Wie wäre es mit android: scaleType = "centerInside" anstelle von android: scaleType = "centerCrop"? Es würde auch nicht das Bild zuschneiden, sondern sicherstellen, dass sowohl Breite als auch Höhe kleiner oder gleich der Breite und Höhe der Bildansicht sind :) Hier ist eine gute visuelle Anleitung für Skalentypen : oughtbot.com/blog/android-imageview-scaletype-a-visual- Führer
Vida
57

Wenn Sie möchten, ImageViewdass beide skaliert werden, während das richtige Seitenverhältnis beibehalten wird, fügen Sie dies Ihrem XML hinzu:

android:adjustViewBounds="true"
android:scaleType="fitCenter"

Fügen Sie dies Ihrem Code hinzu:

// We need to adjust the height if the width of the bitmap is
// smaller than the view width, otherwise the image will be boxed.
final double viewWidthToBitmapWidthRatio = (double)image.getWidth() / (double)bitmap.getWidth();
image.getLayoutParams().height = (int) (bitmap.getHeight() * viewWidthToBitmapWidthRatio);

Es hat eine Weile gedauert, bis dies funktioniert hat, aber dies scheint in den Fällen zu funktionieren, in denen das Bild kleiner als die Bildschirmbreite und größer als die Bildschirmbreite ist und das Bild nicht verpackt wird.

Kevin
quelle
1
Warum nicht einfach android: scaleType = "centerCrop" verwenden?
Lukas Batteau
funktioniert wie ein Zauber, danke. scaleType hängt von der Situation ab, zum Beispiel brauchte ich genau das.
David
Dies ist eine etwas barbarische Methode, um die Größe der Ansicht zu ändern. Was passiert, wenn sich die Ansichtsgrenzen ändern, nachdem Sie die Bitmap auf ImageView festgelegt haben? Aus diesem Grund sollte dies in onMeasure () erfolgen, das implementiert werden kann, wenn Sie eine benutzerdefinierte Unterklasse von ImageView erstellen.
Aron Lorincz
1
Alles was ich brauchte war das fitCenter und adjustViewBounds, der Rest des Codes war zumindest für mich unnötig
kingargyle
Dies funktioniert für mich und muss keinen Code hinzufügen. Ohne die adjustViewBounds wurde die Bildbreite, wenn sie kleiner als die imageView-Breite war, nicht vergrößert, sodass die Höhe auf die native Höhe angehalten wurde und auf der Breite einige Bänder angezeigt wurden.
Cristi Băluță
15

Das hat bei mir funktioniert:

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="39dip"
android:scaleType="centerCrop"
android:adjustViewBounds ="true"
Mike6679
quelle
10

Das hat mein Problem gelöst

android:adjustViewBounds="true"
android:scaleType="fitXY"
Shafiq-ur-Rehman
quelle
Das Seitenverhältnis des Bildes bleibt für mich nicht erhalten.
Dmitry
9

Unterer Code Arbeiten für Skalierungsbild als Seitenverhältnis:

Bitmap bitmapImage = BitmapFactory.decodeFile("Your path");
int nh = (int) ( bitmapImage.getHeight() * (512.0 / bitmapImage.getWidth()) );
Bitmap scaled = Bitmap.createScaledBitmap(bitmapImage, 512, nh, true);
your_imageview.setImageBitmap(scaled);
Mukesh Parmar
quelle
8

Schauen Sie sich ImageView.ScaleType an, um zu steuern und zu verstehen, wie die Größenänderung in einem erfolgt ImageView. Wenn die Bildgröße geändert wird (unter Beibehaltung des Seitenverhältnisses), besteht die Möglichkeit, dass entweder die Höhe oder Breite des Bilds kleiner als ImageViewdie Abmessungen des Bildes wird .

Samuh
quelle
6

Verwenden Sie diese Eigenschaften in ImageView, um das Seitenverhältnis beizubehalten:

android:adjustViewBounds="true"
android:scaleType="fitXY"

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    />
Atif Mahmood
quelle
Nur diese Antwort hat mir geholfen. Vielen Dank!
Dmitry
6

So hat es bei mir in einem ConstraintLayout funktioniert:

<ImageView
    android:id="@+id/myImg"
    android:layout_width="300dp"
    android:layout_height="300dp"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true"/>

Dann setze ich im Code das Zeichenbare wie folgt:

ImageView imgView = findViewById(R.id.myImg);
imgView.setImageDrawable(ResourcesCompat.getDrawable(getResources(), R.drawable.image_to_show, null));

Dies passt gut zum Bildverhältnis und hält es in der Mitte.

Jeet
quelle
5

Ich habe ein Bild, das kleiner als der Bildschirm ist. Um es proportional zum Maximum zu dehnen und in der Ansicht zu zentrieren, musste ich den folgenden Code verwenden:

<ImageView
    android:id="@+id/my_image"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_centerInParent="true"
    android:adjustViewBounds="true"
    android:layout_weight="1"
    android:scaleType="fitCenter" />

Beachten Sie jedoch, dass einige Elemente, die über ein relatives Layout verfügen und so eingestellt sind, dass sie sich über oder unter der ImageView befinden, höchstwahrscheinlich vom Bild überlappt werden.

Halxinat
quelle
4

Wenn die Bildqualität abnimmt: Verwenden Sie

android:adjustViewBounds="true"

anstatt

android:adjustViewBounds="true"
android:scaleType="fitXY"
DeveloperSumit
quelle
3

Für alle unter Ihnen, die möchten, dass das Bild genau der Bildansicht mit der richtigen Skalierung und ohne Zuschneiden entspricht

imageView.setScaleType(ScaleType.FIT_XY);

Dabei ist imageView die Ansicht, die Ihre ImageView darstellt

Ein Bewusstsein
quelle
4
Nein, dies ändert das Seitenverhältnis. In den Dokumenten heißt es: "Skalieren Sie X und Y unabhängig voneinander, sodass src genau mit dst übereinstimmt. Dies kann das Seitenverhältnis von src ändern."
Rose Perrone
Übrigens kann dieses FIT_XY nicht zum Ändern der Breite / Höhe des Bildes für die Anzeige in der Bildansicht verwendet werden.
Bay
3

Sie können die Bildschirmbreite berechnen. Und Sie können die Bitmap skalieren.

 public static float getScreenWidth(Activity activity) {
        Display display = activity.getWindowManager().getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics();
        display.getMetrics(outMetrics);
        float pxWidth = outMetrics.widthPixels;
        return pxWidth;
    }

Berechnen Sie die Bildschirmbreite und die skalierte Bildhöhe anhand der Bildschirmbreite.

float screenWidth=getScreenWidth(act)
  float newHeight = screenWidth;
  if (bitmap.getWidth() != 0 && bitmap.getHeight() != 0) {
     newHeight = (screenWidth * bitmap.getHeight()) / bitmap.getWidth();
  }

Nachdem Sie die Bitmap skalieren können.

Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, (int) screenWidth, (int) newHeight, true);
Android-Entwickler
quelle
3

Wenn Sie dies programmgesteuert tun, rufen Sie die Setter in der richtigen Reihenfolge auf:

imageView.setAdjustViewBounds(true)
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP)
lukas
quelle
2

Wenn Sie möchten, dass Ihr Bild den maximal möglichen Platz einnimmt, ist dies die beste Option

android:layout_weight="1"
android:scaleType="fitCenter"
Mohsen Afshin
quelle
2

Du brauchst keinen Java-Code. Du musst nur :

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

Der Schlüssel befindet sich im übergeordneten Element für Breite und Höhe

Romu Dizzy
quelle
1

Versuchen Sie es mit android:layout_gravityImageView:

android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_weight="1"

Das obige Beispiel hat bei mir funktioniert.

ITisha
quelle
1
android: layout_weight = "1" ist der Schlüssel.
Nima
1

Ich habe einen Algorithmus, um eine Bitmap so zu skalieren, dass sie am besten zu den Containerabmessungen passt, wobei das Seitenverhältnis beibehalten wird. Bitte finden meine Lösung hier

Hoffe, das hilft jemandem auf der Straße!

Parth Kapoor
quelle
0

Ich benutze das:

<ImageView
android:id="@+id/logo"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_centerInParent="true"
android:scaleType="centerInside"
android:src="@drawable/logo" />
Flavio Capaccio
quelle
0

Im Falle der Verwendung cardviewzum Runden imageviewund Fixieren android:layout_heightfür den Header funktionierte dies für mich, um das Bild mit zu ladenGlide

    <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
             xmlns:tools="http://schemas.android.com/tools"
             android:layout_width="match_parent"
             android:layout_height="220dp"
             xmlns:card_view="http://schemas.android.com/apk/res-auto"
             >

    <android.support.v7.widget.CardView
            android:id="@+id/card_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center|top"
            card_view:cardBackgroundColor="@color/colorPrimary"
            card_view:cardCornerRadius="10dp"
            card_view:cardElevation="10dp"
            card_view:cardPreventCornerOverlap="false"
            card_view:cardUseCompatPadding="true">

        <ImageView
                android:adjustViewBounds="true"
                android:maxHeight="220dp"
                android:id="@+id/iv_full"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:scaleType="fitCenter"/>

    </android.support.v7.widget.CardView>
</FrameLayout>
lvl4fi4
quelle
0

Sie können ein Bild skalieren, das auch die Größe Ihres Bildes verringert. Es gibt eine Bibliothek dafür, die Sie herunterladen und verwenden können. https://github.com/niraj124124/Images-Files-scale-and-compress.git

Verwendung 1) Importieren Sie den Compressor-v1.0. Glas zu Ihrem Projekt. 2) Fügen Sie zum Testen den folgenden Beispielcode hinzu. ResizeLimiter resize = ImageResizer.build (); resize.scale ("inputImagePath", "outputImagePath", imageWidth, imageHeight); Je nach Ihren Anforderungen gibt es viele weitere Methoden

Niraj
quelle
0

Übergeben Sie Ihre ImageView und basierend auf Bildschirmhöhe und -breite können Sie sie erstellen

    public void setScaleImage(EventAssetValueListenerView view){
        // Get the ImageView and its bitmap
        Drawable drawing = view.getDrawable();
        Bitmap bitmap = ((BitmapDrawable)drawing).getBitmap();
        // Get current dimensions
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();

        float xScale = ((float) 4) / width;
        float yScale = ((float) 4) / height;
        float scale = (xScale <= yScale) ? xScale : yScale;

        Matrix matrix = new Matrix();
        matrix.postScale(scale, scale);

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

        view.setImageDrawable(result);

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

ppreetikaa
quelle
0

Schnelle Antwort:

<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" />
myworldbox
quelle
-5
imageView.setImageBitmap(Bitmap.createScaledBitmap(bitmap, 130, 110, false));
user2099162
quelle