ImageView - Höhe mit Breite übereinstimmen?

166

Ich habe eine Bildansicht. Ich möchte, dass seine Breite fill_parent ist. Ich möchte, dass seine Höhe unabhängig von der Breite ist. Beispielsweise:

<ImageView
  android:layout_width="fill_parent"
  android:layout_height="whatever the width ends up being" />

Ist so etwas in einer Layoutdatei möglich, ohne dass ich meine eigene Ansichtsklasse erstellen muss?

Vielen Dank

user291701
quelle
Haben Sie herausgefunden, wie das geht? Ich gehe davon aus, dass das Seitenverhältnis gleich bleiben soll. Bei den meisten dieser Antworten wird davon ausgegangen, dass das Bild quadratisch sein soll.
Adam
@ Joe Blow, das ist ein sehr schlechter Weg, es zu tun
Aggressor

Antworten:

170

Update: 14. September 2017

Laut einem Kommentar unten ist die prozentuale Support-Bibliothek ab Android Support Library 26.0.0 veraltet. Dies ist der neue Weg, dies zu tun:

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:1" />

</android.support.constraint.ConstraintLayout>

Siehe hier

Veraltet:

Laut diesem Beitrag von Android-Entwicklern müssen Sie jetzt nur noch alles, was Sie wollen, in ein PercentRelativeLayout oder ein PercentFrameLayout einbinden und dann die Verhältnisse wie folgt angeben

<android.support.percent.PercentRelativeLayout 
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        app:layout_widthPercent="100%"
        app:layout_aspectRatio="100%"/>

</android.support.percent.PercentRelativeLayout>
Davidchuyaya
quelle
8
Der Link dieser Antwort hat die eleganteste Lösung von Google. In meinem Fall wollte ich, dass das Bild im Verhältnis 16: 9 angezeigt wird, unabhängig vom ursprünglichen Bildseitenverhältnis. Funktioniert super. Vielen Dank!
LETs
In meinem Fall haben Lösungen wie diese nicht funktioniert, diese haben funktioniert!
Gooey
5
Vergessen Sie nicht, 'compile com.android.support:percent:23.3.0' in Ihre Abhängigkeiten aufzunehmen
Milad Faridnia
Es sieht so aus, als ob dieser Ansatz Probleme mit WrappedViewPager hat, der die Höhe basierend auf den untergeordneten Inhalten berechnet. Quelle für WrappedViewPager ähnlich wie gist.github.com/egslava/589b82a6add9c816a007
sha
1
Das Percent Support-Modul ist seit der Android-Support-Bibliothek 26.0.0 veraltet. Quelle: developer.android.com/topic/libraries/support-library/…
MHogge
96

Vielleicht beantwortet dies Ihre Frage:

<ImageView
    android:id="@+id/cover_image"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:scaleType="fitCenter"
    android:adjustViewBounds="true" />

Sie können das scaleTypeAttribut für diese spezielle Situation ignorieren .

Vlad Stefanescu
quelle
12
Ja, das ist nutzlos
Fattie
4
Es ist nicht unbedingt nutzlos. Dies funktioniert gut für meine Verwendung. Ich habe ein Symbol in einer Titelleiste, das ich skalieren möchte, um die Höhe zu füllen, während ich quadratisch bleibe.
Anubian Noob
3
Mein Problem wurde auch gelöst.
Dielson Sales
Der einfachste Weg! Dies sollte als beste Antwort markiert werden.
H. Farid
30

Dies kann mithilfe von LayoutParams erfolgen, um die Höhe der Ansichten dynamisch festzulegen, sobald Sie die Breite der Ansichten zur Laufzeit kennen. Sie müssen einen ausführbaren Thread verwenden, um die Breite der Ansichten zur Laufzeit zu ermitteln. Andernfalls versuchen Sie, die Höhe festzulegen, bevor Sie die Breite der Ansicht kennen, da das Layout noch nicht gezeichnet wurde.

Beispiel, wie ich mein Problem gelöst habe:

final FrameLayout mFrame = (FrameLayout) findViewById(R.id.frame_id);

    mFrame.post(new Runnable() {

        @Override
        public void run() {
            RelativeLayout.LayoutParams mParams;
            mParams = (RelativeLayout.LayoutParams) mFrame.getLayoutParams();
            mParams.height = mFrame.getWidth();
            mFrame.setLayoutParams(mParams);
            mFrame.postInvalidate();
        }
    });

Die LayoutParams müssen vom Typ der übergeordneten Ansicht sein, in der sich Ihre Ansicht befindet. Mein FrameLayout befindet sich in einem RelativeLayout in der XML-Datei.

    mFrame.postInvalidate();

wird aufgerufen, um zu erzwingen, dass die Ansicht in einem anderen Thread als dem UI-Thread neu gezeichnet wird

drees
quelle
4
tolle Antwort, besonders mit dem Runnable, danke!
jesses.co.tt
1
Dies funktioniert zwar, ist aber nicht ideal. Auf Post ausführen bedeutet, dass die Ansicht einmal gerendert wird, bevor sich das Layout ändert. Möglicherweise wird ein Flash von Inhalten in der falschen Höhe zugelassen, bevor richtig gezeichnet wird. Besser früher lösen. Der frühestmögliche Moment zum Lösen ist während eines Brauchs onMeasure, wie in Regis 'Antwort gezeigt . Eine Alternative, aber nur für Ansichten, die über einen Adapter, z. B. im Inneren GridView, gerendert werden , ist Matts Antwort .
ToolmakerSteve
1
Nun, es hat bei mir erst nach dem Aufruf requestLayout()nach dem Einstellen der Parameter funktioniert . warum sollte das so sein?
Divins Mathew
mFrame.postInvalidate (); ist das, was es getan hat, ohne es bekam ich den Blick aus der Position.
Jacolack
17

Ich konnte David Chus Antwort nicht dazu bringen , für ein RecyclerView-Element zu arbeiten, und fand heraus, dass ich das ImageView auf das übergeordnete Element beschränken musste. Stellen Sie die ImageView-Breite auf ein 0dpund beschränken Sie den Anfang und das Ende auf das übergeordnete Element . Ich bin nicht sicher, ob die Breite auf eingestellt ist wrap_contentoder match_parentin einigen Fällen funktioniert, aber ich denke, dies ist eine bessere Möglichkeit, das untergeordnete Element eines ConstraintLayout dazu zu bringen, sein übergeordnetes Element zu füllen.

<android.support.constraint.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintDimensionRatio="1:1"/>

</android.support.constraint.ConstraintLayout>
Shawn Aten
quelle
13

Hier habe ich was ich getan habe, um einen ImageButton zu haben, dessen Breite immer gleich seiner Höhe ist (und dumme leere Ränder in eine Richtung vermeiden ... die ich als Fehler des SDK betrachte ...):

Ich habe eine SquareImageButton-Klasse definiert, die sich von ImageButton aus erstreckt:

package com.myproject;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageButton;

    public class SquareImageButton extends ImageButton {

        public SquareImageButton(Context context) {
        super(context);


        // TODO Auto-generated constructor stub
    }

    public SquareImageButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub

    }

    public SquareImageButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub

    }

    int squareDim = 1000000000;

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);


        int h = this.getMeasuredHeight();
        int w = this.getMeasuredWidth();
        int curSquareDim = Math.min(w, h);
        // Inside a viewholder or other grid element,
        // with dynamically added content that is not in the XML,
        // height may be 0.
        // In that case, use the other dimension.
        if (curSquareDim == 0)
            curSquareDim = Math.max(w, h);

        if(curSquareDim < squareDim)
        {
            squareDim = curSquareDim;
        }

        Log.d("MyApp", "h "+h+"w "+w+"squareDim "+squareDim);


        setMeasuredDimension(squareDim, squareDim);

    }

}

Hier ist meine XML:

<com.myproject.SquareImageButton
            android:id="@+id/speakButton"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:scaleType="centerInside"
            android:src="@drawable/icon_rounded_no_shadow_144px"
            android:background="#00ff00"
            android:layout_alignTop="@+id/searchEditText"
            android:layout_alignBottom="@+id/searchEditText"
            android:layout_alignParentLeft="true"
           />

Klappt wunderbar !

Regis_AG
quelle
Ja, das ist die beste Antwort. (und die einzige, die wirklich der OP-Frage entspricht)
Twometer
6

In Android 26.0.0 ist PercentRelativeLayout veraltet .

Der beste Weg, es zu lösen, ist jetzt ConstraintLayoutwie folgt :

<android.support.constraint.ConstraintLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

    <ImageView android:layout_width="match_parent"
               android:layout_height="0dp"
               android:scaleType="centerCrop"
               android:src="@drawable/you_image"                       
               app:layout_constraintDimensionRatio="1:1"/>


</android.support.constraint.ConstraintLayout>


Hier finden Sie ein Tutorial zum Hinzufügen ConstraintLayoutzu Ihrem Projekt.

Sebastian Schneider
quelle
6

Wenn sich Ihre Bildansicht in einem Einschränkungslayout befindet, können Sie die folgenden Einschränkungen verwenden, um eine quadratische Bildansicht zu erstellen

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:id="@+id/ivImageView"
    app:layout_constraintDimensionRatio="W,1:1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintEnd_toEndOf="parent"/>
ChaturaM
quelle
5

Sie können es nicht allein mit dem Layout machen, ich habe es versucht. Am Ende habe ich eine sehr einfache Klasse geschrieben, um damit umzugehen. Sie können sie auf Github nachlesen. SquareImage.java Es ist Teil eines größeren Projekts, aber nichts, was durch ein kleines Kopieren und Einfügen nicht behoben werden kann (lizenziert unter Apache 2.0).

Im Wesentlichen müssen Sie nur die Höhe / Breite gleich der anderen Dimension einstellen (je nachdem, wie Sie sie skalieren möchten).

Hinweis: Mit dem scaleTypeAttribut können Sie es ohne benutzerdefinierte Klasse quadratisch machen , aber die Grenzen der Ansicht erstrecken sich über das sichtbare Bild hinaus. Dies macht es zu einem Problem, wenn Sie andere Ansichten in der Nähe platzieren.

smith324
quelle
3

Um Ihre ImageView auf die Hälfte des Bildschirms einzustellen, müssen Sie Ihrem XML für die ImageView Folgendes hinzufügen:

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

Um dann die Höhe auf diese Breite einzustellen, müssen Sie dies im Code tun. Stellen Sie in der getViewMethode Ihres GridViewAdapters die ImageViewHöhe gleich der gemessenen Breite ein:

mImageView.getLayoutParams().height = mImageView.getMeasuredWidth();
Matt Logan
quelle
3

Für Passanten, die 2017 vorbeikommen, ist der neue beste Weg, um das zu erreichen, was Sie wollen, die Verwendung von ConstraintLayout wie folgt :

<ImageView
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:scaleType="centerCrop"
    app:layout_constraintDimensionRatio="1:1" />

Vergessen Sie nicht, allen vier Richtungen Einschränkungen hinzuzufügen, die von Ihrem Layout benötigt werden.

Erstellen Sie mit ConstraintLayout eine reaktionsschnelle Benutzeroberfläche

Darüber hinaus ist PercentRelativeLayout inzwischen veraltet (siehe Android-Dokumentation ).

Cristina De Rito
quelle
1

So habe ich dieses Problem gelöst:

int pHeight =  picture.getHeight();
int pWidth = picture.getWidth();
int vWidth = preview.getWidth();
preview.getLayoutParams().height = (int)(vWidth*((double)pHeight/pWidth));

Vorschau - imageView mit einer Breite von "match_parent" und scaleType von "cropCenter"

picture - Bitmap-Objekt, das in imageView src festgelegt werden soll.

Das funktioniert ziemlich gut für mich.

Udenfox
quelle
Sie haben nicht erklärt, wo dieser Code abgelegt werden muss. Sie haben auch nicht erklärt, warum Sie dies = vw*ph/pwanstelle des einfacheren tun = vw. (Ich denke, Sie tun dies, um das Seitenverhältnis des Quellbildes beizubehalten, anstatt eine quadratische Vorschau zu erzwingen.)
ToolmakerSteve
0

Ich glaube nicht, dass Sie dies in einer XML-Layoutdatei tun können, und ich glaube nicht, dass das android:scaleTypeAttribut so funktioniert, wie Sie es möchten.
Der einzige Weg wäre, dies programmgesteuert zu tun. Sie können die Breite auf fill_parent setzen und entweder die Bildschirmbreite als Höhe der Viewoder die View.getWidth()Methode verwenden.

Anfänger
quelle
0

Die ImageView-Funktion "scaleType" kann Ihnen hier weiterhelfen.

Dieser Code behält das Seitenverhältnis bei und positioniert das Bild oben:

android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitStart"

Hier ist ein großartiger Beitrag, der die Möglichkeiten und Erscheinungsformen der Verwendung von scaleType zeigt.

ImageView scaleType-Beispiele

ac_banks
quelle
"scaleType" hilft hier nicht weiter. Das Ziel ist, dass die ImageView selbst immer quadratisch ist, nicht nur das Bild darin. Bei scaleType ist die ImageView möglicherweise größer als das Bild.
ToolmakerSteve
0

das hat mir gefallen -

layout.setMinimumHeight(layout.getWidth());
HarshitG
quelle