ImageView - a altura corresponde à largura?


166

Eu tenho uma visualização de imagem. Eu quero que sua largura seja fill_parent. Eu quero que a altura seja a largura que for. Por exemplo:

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

É possível algo assim em um arquivo de layout sem precisar criar minha própria classe de exibição?

obrigado


Você descobriu como fazer isso? Suponho que você deseja que a proporção permaneça a mesma. A maioria dessas respostas pressupõe que você deseja que a imagem seja quadrada.
8113 Adam

@ Joe Blow, que é uma péssima maneira de fazer isso #
Aggressor

Respostas:


170

Atualização: 14 de setembro de 2017

De acordo com um comentário abaixo, a porcentagem de biblioteca de suporte está obsoleta a partir da Android Support Library 26.0.0. Esta é a nova maneira de fazer isso:

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

Veja aqui

Descontinuada:

De acordo com esta postagem dos desenvolvedores do Android, tudo o que você precisa fazer agora é agrupar o que quiser dentro de um PercentRelativeLayout ou um PercentFrameLayout e especificar suas proporções, assim

<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
O link para esta resposta tem a solução mais elegante fornecida ao Google. No meu caso, queria que a imagem fosse exibida na proporção 16: 9, independentemente da proporção original da imagem. Funciona bem. Obrigado!
Deixou

No meu caso, soluções como esta não funcionaram, esta funcionou!
Gooey

5
Não se esqueça de adicionar 'com.android.support:percent:23.3.0 compilação' em suas dependências
Milad Faridnia

Parece que essa abordagem está tendo problemas com o WrappedViewPager, que calcula a altura com base no conteúdo filho. Fonte para WrappedViewPager semelhante a gist.github.com/egslava/589b82a6add9c816a007
sha

1
O módulo Porcentagem de suporte foi descontinuado desde a biblioteca de suporte do Android 26.0.0. Fonte: developer.android.com/topic/libraries/support-library/…
MHogge

97

Talvez isso responda sua pergunta:

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

Você pode ignorar o scaleTypeatributo para esta situação específica.


12
Sim, isso é inútil
Fattie

4
Não é necessariamente inútil. Isso funciona bem para o meu uso. Eu tenho um ícone na barra de título que eu quero dimensionar para preencher a altura enquanto permanece quadrado.
Anubian Noob

3
Também resolveu o meu problema.
Dielson Sales

A maneira mais fácil! Isso deve ser marcado como a melhor resposta.
H. Farid

30

Isso pode ser feito usando o LayoutParams para definir dinamicamente a altura das Views assim que você souber a largura das Views em tempo de execução. Você precisa usar um thread Runnable para obter a largura da Views em tempo de execução, ou então você estará tentando definir a Altura antes de saber a largura da View porque o layout ainda não foi desenhado.

Exemplo de como eu resolvi meu 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();
        }
    });

Os LayoutParams devem ser do tipo da Visualização pai em que sua visualização está. Meu FrameLayout está dentro de um RelativeLayout no arquivo xml.

    mFrame.postInvalidate();

é chamado para forçar a exibição a redesenhar enquanto estiver em um thread separado do que o thread da interface do usuário


4
resposta incrível, especialmente com o Runnable, obrigado!
precisa saber é o seguinte

1
Enquanto isso funciona, não é o ideal. A execução na postagem significa que a exibição é renderizada uma vez antes da alteração do layout. Pode permitir um flash de conteúdo na altura errada, antes de desenhar corretamente. Melhor resolver mais cedo. O primeiro momento possível para resolver é durante um costume onMeasure, como mostra a resposta da Regis . Uma alternativa, mas apenas para visualizações renderizadas através de um adaptador, por exemplo GridView, dentro , é a resposta de Matt .
ToolmakerSteve

1
bem, funcionou para mim apenas depois de ligar requestLayout()depois de definir os parâmetros. por que isso seria?
precisa

mFrame.postInvalidate (); foi o que fez, sem ele eu estava tirando a vista da posição.
Jacolack

17

Não consegui que a resposta de David Chu funcionasse para um item do RecyclerView e concluí que precisava restringir o ImageView ao pai. Defina a largura do ImageView 0dpe restrinja seu início e fim ao pai. Não tenho certeza se definir a largura como wrap_contentou match_parentfunciona em alguns casos, mas acho que essa é a melhor maneira de fazer com que o filho de um ConstraintLayout preencha seu pai.

<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

Aqui eu o que fiz para ter um ImageButton que sempre tem uma largura igual à sua altura (e evite margens vazias estúpidas em uma direção ... que considero um bug do SDK ...):

Eu defini uma classe SquareImageButton que se estende do 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);

    }

}

Aqui está o meu 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"
           />

Funciona como um encanto !


Sim, essa é a melhor resposta. (e o único que realmente corresponde a questão PO)
Twometer

6

No Android 26.0.0, o PercentRelativeLayout foi descontinuado .

A melhor maneira de resolver isso agora é ConstraintLayoutassim:

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


Aqui está um tutorial sobre como adicionar ConstraintLayoutao seu projeto.


6

Se a visualização da imagem estiver dentro de um layout de restrição, você poderá usar as seguintes restrições para criar uma visualização quadrada da imagem

<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

Você não pode fazer isso apenas com o layout, tentei. Acabei escrevendo uma aula muito simples para lidar com isso, você pode conferir no github. SquareImage.java Faz parte de um projeto maior, mas nada que uma pequena cópia e cola não pode consertar (licenciado no Apache 2.0)

Basicamente, você só precisa definir a altura / largura igual à outra dimensão (dependendo da maneira que você deseja dimensioná-la)

Nota: Você pode quadrá-lo sem uma classe personalizada usando o scaleTypeatributo, mas os limites da vista se estendem além da imagem visível, o que torna um problema se você estiver colocando outras vistas perto dele.


3

Para definir seu ImageView igual à metade da tela, você precisa adicionar o seguinte ao XML para o ImageView:

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

Para definir a altura igual a essa largura, você precisa fazer isso no código. No getViewmétodo do seu GridViewadaptador, defina a ImageViewaltura igual à sua largura medida:

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

3

Para as pessoas que passam agora, em 2017, a nova melhor maneira de alcançar o que você deseja é usando o ConstraintLayout assim:

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

E não se esqueça de adicionar restrições a todas as quatro direções, conforme necessário pelo seu layout.

Crie uma interface de usuário responsiva com ConstraintLayout

Além disso, agora, o PercentRelativeLayout foi descontinuado (consulte a documentação do Android ).


1

Aqui está como eu resolvi esse problema:

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

preview - imageView com largura definida como "match_parent" e scaleType como "cropCenter"

picture - Objeto Bitmap para definir no imageView src.

Isso funciona muito bem para mim.


Você não explicou onde esse código deve ser colocado. Você também não explicou por que o faz, em = vw*ph/pwvez do mais simples = vw. (Eu acho que você fazer isso para preservar a relação de aspecto de imagem de origem de, ao invés da força um preview quadrado.)
ToolmakerSteve

0

Acho que não há como você fazer isso no arquivo de layout XML, e não acho que o android:scaleTypeatributo funcione como você deseja.
A única maneira seria fazê-lo programaticamente. Você pode definir a largura como fill_parent e pode ter a largura da tela como a altura do método Viewou pode usar View.getWidth().


0

A função ImageView "scaleType" pode ajudá-lo aqui.

Este código manterá a proporção e posicionará a imagem no topo:

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

Aqui está um ótimo post mostrando as possibilidades e aparências do uso de scaleType.

ImageView scaleType samples


"scaleType" não ajuda aqui. O objetivo é manter o ImageView sempre quadrado, não apenas a imagem dentro dele. Com scaleType, o ImageView pode ser maior que a imagem.
Página

0

eu fiz assim -

layout.setMinimumHeight(layout.getWidth());
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.