ImageView: la larghezza corrisponde all'altezza?


166

Ho una visione d'immagine. Voglio che la sua larghezza sia fill_parent. Voglio che la sua altezza sia qualunque sia la larghezza. Per esempio:

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

È possibile qualcosa di simile in un file di layout senza dover creare la mia classe di visualizzazione?

Grazie


Hai capito come fare? Suppongo che desideri che le proporzioni rimangano le stesse. La maggior parte di queste risposte presuppone che l'immagine sia quadrata.
Adam,

@Joe Blow che è un modo MOLTO brutto per farlo
Aggressor

Risposte:


170

Aggiornamento: 14 settembre 2017

Secondo un commento di seguito, la libreria di supporto percentuale è obsoleta a partire dalla Libreria di supporto Android 26.0.0. Questo è il nuovo modo di farlo:

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

Vedi qui

deprecato:

Secondo questo post di Android Developers, tutto ciò che devi fare ora è avvolgere tutto ciò che vuoi in un PercentRelativeLayout o un PercentFrameLayout e quindi specificare i suoi rapporti, in questo modo

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

8
Il link a questa risposta ha la soluzione più elegante fornita da Google. Nel mio caso, volevo che l'immagine venisse visualizzata nel rapporto 16: 9, indipendentemente dalle proporzioni dell'immagine originale. Funziona alla grande. Grazie!
Lascia il

Nel mio caso, soluzioni come questa non hanno funzionato, questa ha funzionato!
Gooey,

5
non dimenticare di aggiungere "compile com.android.support:percent:23.3.0" nelle tue dipendenze
Milad Faridnia,

Sembra che questo approccio abbia problemi con WrappedViewPager che calcola l'altezza in base al contenuto dei suoi figli. Fonte per WrappedViewPager simile a gist.github.com/egslava/589b82a6add9c816a007
sha

1
Il modulo Supporto percentuale è stato deprecato è stato deprecato dalla libreria di supporto Android 26.0.0. Fonte: developer.android.com/topic/libraries/support-library/…
MHogge,

97

Forse questo risponderà alla tua domanda:

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

È possibile ignorare l' scaleTypeattributo per questa situazione particolare.


12
Sì, è inutile
Fattie

4
Non è necessariamente inutile. Funziona bene per il mio uso, ho un'icona su una barra del titolo che voglio ridimensionare per riempire l'altezza rimanendo quadrata.
Anubian Noob,

3
Risolto anche il mio problema.
Dielson Sales,

La via più facile! Questo dovrebbe essere contrassegnato come la migliore risposta.
H. Farid,

30

Questo può essere fatto usando LayoutParams per impostare dinamicamente l'altezza di Views una volta che conosci la larghezza di Views in fase di esecuzione. È necessario utilizzare un thread Runnable per ottenere la larghezza di Views in fase di esecuzione, altrimenti si proverà a impostare l'altezza prima di conoscere la larghezza della vista perché il layout non è stato ancora disegnato.

Esempio di come ho risolto il mio problema:

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

LayoutParams deve essere del tipo di Vista padre in cui si trova la vista. Il mio FrameLayout è all'interno di un RelativeLayout nel file xml.

    mFrame.postInvalidate();

viene chiamato per forzare il ridisegno della vista su un thread separato rispetto al thread dell'interfaccia utente


4
risposta fantastica, soprattutto con Runnable, grazie!
jesses.co.tt

1
Mentre funziona, non è l'ideale. In esecuzione su post significa che la visualizzazione viene visualizzata una volta prima che il layout cambi. Potrebbe consentire un lampo di contenuto all'altezza sbagliata, prima di disegnare correttamente. Meglio risolvere prima. Il primo momento possibile da risolvere è durante un'usanza onMeasure, come mostrato nella risposta di Regis . Un'alternativa, ma solo per le viste rese tramite un adattatore, ad esempio all'interno GridView, è la risposta di Matt .
ToolmakerSteve

1
bene ha funzionato per me solo dopo aver chiamato requestLayout()dopo aver impostato i parametri. perché dovrebbe essere?
Divins Mathew il

mFrame.postInvalidate (); è quello che ha fatto, senza di esso stavo togliendo la vista dalla posizione.
Jacolack,

17

Non sono riuscito a far funzionare la risposta di David Chu per un oggetto RecyclerView e ho capito che dovevo vincolare ImageView al genitore. Impostare la larghezza di ImageView su 0dpe vincolarne l'inizio e la fine al genitore. Non sono sicuro che l'impostazione della larghezza su wrap_contento match_parentfunzioni in alcuni casi, ma penso che questo sia un modo migliore per far sì che il figlio di un ConstraintLayout riempia il suo genitore.

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

13

Ecco cosa ho fatto per avere un ImageButton che ha sempre una larghezza uguale alla sua altezza (ed evitare stupidi margini vuoti in una direzione ... che considero un bug dell'SDK ...):

Ho definito una classe SquareImageButton che si estende da ImageButton:

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

    }

}

Ecco il mio 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"
           />

Funziona come un fascino!


Sì, questa è la risposta migliore. (e l'unico che corrisponde davvero alla domanda dei PO)
Twometer

6

In Android 26.0.0 PercentRelativeLayout è stato deprecato .

Il modo migliore per risolverlo è ora con ConstraintLayoutquesto:

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


Ecco un tutorial su come aggiungere ConstraintLayoutal tuo progetto.


6

Se la vista dell'immagine è all'interno di un layout di vincolo, è possibile utilizzare i seguenti vincoli per creare una vista di immagine quadrata

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

5

Non posso farlo solo con il layout, ho provato. Ho finito per scrivere una lezione molto semplice per gestirla, puoi verificarla su github. SquareImage.java Fa parte di un progetto più ampio, ma nulla può essere risolto da un po 'di copia e incolla (concesso in licenza con Apache 2.0)

Fondamentalmente devi solo impostare l'altezza / larghezza uguale all'altra dimensione (a seconda del modo in cui vuoi ridimensionarla)

Nota: è possibile renderlo quadrato senza una classe personalizzata utilizzando l' scaleTypeattributo ma i limiti della vista si estendono oltre l'immagine visibile, il che lo rende un problema se si posizionano altre viste accanto.


3

Per impostare ImageView uguale alla metà dello schermo, è necessario aggiungere quanto segue al proprio XML per ImageView:

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

Per impostare quindi l'altezza uguale a questa larghezza, è necessario farlo nel codice. Nel getViewmetodo GridViewdell'adattatore, imposta l' ImageViewaltezza uguale alla sua larghezza misurata:

mImageView.getLayoutParams().height = mImageView.getMeasuredWidth();

3

Per le persone che passano ormai, nel 2017, il nuovo modo migliore per ottenere ciò che desideri è utilizzare ConstraintLayout in questo modo:

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

E non dimenticare di aggiungere vincoli a tutte e quattro le direzioni come richiesto dal layout.

Crea un'interfaccia utente reattiva con ConstraintLayout

Inoltre, ormai, PercentRelativeLayout è stato deprecato (consultare la documentazione di Android ).


1

Ecco come ho risolto questo problema:

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

preview - imageView con larghezza impostata su "match_parent" e scaleType su "cropCenter"

picture - Oggetto Bitmap da impostare in imageView src.

Funziona abbastanza bene per me.


Non hai spiegato dove inserire questo codice. Inoltre non hai spiegato perché lo fai = vw*ph/pwinvece del più semplice = vw. (Penso che lo
facciate

0

Non credo che ci sia alcun modo per farlo nel file di layout XML e non credo che l' android:scaleTypeattributo funzionerà come vorresti che fosse.
L'unico modo sarebbe farlo programmaticamente. È possibile impostare la larghezza su fill_parent e prendere la larghezza dello schermo come altezza del metodo Viewoppure utilizzare il View.getWidth()metodo.


0

La funzione "scaleType" di ImageView può aiutarti qui.

Questo codice manterrà le proporzioni e posizionerà l'immagine in alto:

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

Ecco un ottimo post che mostra le possibilità e le apparenze dell'uso di scaleType.

Scala ImageView Esempi di tipo


"scaleType" non aiuta qui. L'obiettivo è che ImageView stesso sia sempre quadrato, non solo l'immagine al suo interno. Con scaleType, ImageView potrebbe essere più grande dell'immagine.
ToolmakerSteve

0

mi è piaciuto questo -

layout.setMinimumHeight(layout.getWidth());
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.