web-dev-qa-db-fra.com

imageview hauteur comme le wrap_content de l'image montrée

Je souhaite que la largeur d'une ImageView soit définie par le parent et que la hauteur soit proportionnelle à l'aspect. La raison en est que le texte suivant s'affiche un TextView que je veux placer juste sous le ImageView.

Je peux afficher l'image correctement en utilisant

Android:layout_width="fill_parent"
Android:layout_height="fill_parent"

cependant, la hauteur d'ImageView devient la hauteur parent qui est beaucoup plus grande que celle de l'image étirée illustrée. Une idée était de rendre le parent plus petit verticalement, mais .. là je ne connais pas encore la taille de l'image étirée.

Ce qui suit ne fonctionne pas car une petite image n'est pas remplie horizontalement.

Android:layout_width="fill_parent"
Android:layout_height="wrap_content"

Déconner avec

Android:layout_height="wrap_content"

car le RelativeLayout qui l'entoure n'aide pas. A également essayé FrameLayout et LinearLayout et a échoué.

Des idées?

35
Scott Johansen

Vous devez définir adjustViewBounds sur true.

imageView.setAdjustViewBounds(true);
79
Kit

Il y a deux cas si votre taille d'image réelle est égale ou supérieure à votre largeur et hauteur ImageView, vous pouvez utiliser la propriété adjustViewBounds et si votre taille d'image réelle est inférieure à la largeur et à la hauteur ImageView, utilisez la propriété scaleType pour afficher l'image dans ImageView en fonction de votre exigence.

1.La taille réelle de l'image est égale ou supérieure à la largeur et la hauteur requises par ImageView.

<ImageView
    Android:layout_width="match_parent" 
    Android:layout_height="wrap_content"
    Android:adjustViewBounds="true"
    Android:src="@drawable/ic_launcher"/>

2.La taille réelle de l'image est inférieure à la largeur et à la hauteur requises pour ImageView.

<ImageView
    Android:layout_width="match_parent" 
    Android:layout_height="wrap_content"
    Android:scaleType="fitXY"
    Android:src="@drawable/ic_launcher"/>
31
Haresh Chhelana

J'ai donc eu le même problème plus d'une fois et en parcourant les réponses stackoverflow existantes, j'ai réalisé qu'aucune réponse ne donne une explication parfaite de la vraie confusion concernant une solution à ce problème. Alors voilà:

API 17+

imageView.setAdjustViewBounds(true);

OU (en XML)

Android:adjustViewBounds="true"

résout le problème, il fonctionne quelle que soit la taille réelle de la ressource d'image, c'est-à-dire qu'il augmentera ou diminuera votre image à la taille souhaitée que vous avez dans votre mise en page.

En dessous de l'API 17

En dessous de l'API 17 Android:adjustViewBounds="true" ne fonctionnera que pour réduire une image, pas pour l'agrandir, c'est-à-dire si la hauteur réelle de la source d'image est inférieure aux dimensions que vous essayez d'atteindre dans votre mise en page, wrap_content utilisera cette hauteur plus petite et n'agrandira pas (agrandir) l'image comme vous le souhaitez.

Et donc pour l'API 17 et les versions antérieures, vous n'avez pas d'autre choix que d'utiliser une ImageView personnalisée pour obtenir ce comportement. Vous pouvez soit écrire une ImageView personnalisée vous-même, soit utiliser une bibliothèque, qui a déjà fait ce travail.

Utiliser une bibliothèque

Il y a probablement plus d'une bibliothèque qui résout ce problème, l'une d'entre elles est:

compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.0'

qui est utilisé comme ceci:

<com.inthecheesefactory.thecheeselibrary.widget.AdjustableImageView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:adjustViewBounds="true"
                Android:src="@drawable/your_drawable"/>

Utilisation d'une vue personnalisée

alternativement à l'utilisation d'une bibliothèque existante, vous pouvez écrire vous-même une vue personnalisée, par exemple:

import Android.content.Context;
import Android.graphics.drawable.Drawable;
import Android.util.AttributeSet;
import Android.view.ViewGroup;
import Android.view.ViewParent;
import Android.widget.ImageView;

public class ScalableImageView extends ImageView {

    boolean adjustViewBounds;

    public ScalableImageView(Context context) {
        super(context);
    }

    public ScalableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ScalableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setAdjustViewBounds(boolean adjustViewBounds) {
        this.adjustViewBounds = adjustViewBounds;
        super.setAdjustViewBounds(adjustViewBounds);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable drawable = getDrawable();
        if (drawable == null) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            return;
        }

        if (adjustViewBounds) {
            int drawableWidth = drawable.getIntrinsicWidth();
            int drawableHeight = drawable.getIntrinsicHeight();
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);

            if (heightMode == MeasureSpec.EXACTLY && widthMode != MeasureSpec.EXACTLY) {
                int height = heightSize;
                int width = height * drawableWidth / drawableHeight;
                if (isInScrollingContainer())
                    setMeasuredDimension(width, height);
                else
                    setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
            } else if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) {
                int width = widthSize;
                int height = width * drawableHeight / drawableWidth;
                if (isInScrollingContainer())
                    setMeasuredDimension(width, height);
                else
                    setMeasuredDimension(Math.min(width, widthSize), Math.min(height, heightSize));
            } else {
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            }
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }

    private boolean isInScrollingContainer() {
        ViewParent parent = getParent();
        while (parent != null && parent instanceof ViewGroup) {
            if (((ViewGroup) parent).shouldDelayChildPressedState()) {
                return true;
            }
            parent = parent.getParent();
        }
        return false;
    }
}

... que vous utiliseriez comme suit (XML):

<com.YOUR_PACKE_NAME.ScalableImageView
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:adjustViewBounds="true"
    Android:src="@drawable/your_drawable" />
6
Simon Mayrshofer

C'était la seule façon de le faire fonctionner, d'avoir le deuxième ImageView au centre et plus petit que le premier ImageView, et le TextView sous le deuxième ImageView.

Malheureusement, il utilise une taille d'image fixe de "200dp" sur le deuxième ImageView, donc il n'a pas la même apparence sur des appareils de tailles différentes.

Cela détruit également mon ViewFlipper, car toute disposition que j'ai essayée autour de la deuxième ImageView et TextView les fait déplacer ou redimensionner.

<RelativeLayout 
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:tools="http://schemas.Android.com/tools" 
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent" >
    <ImageView
        Android:id="@+id/imageview1"
        Android:contentDescription="@string/desc"
        Android:layout_width="fill_parent"
        Android:layout_height="fill_parent"
        Android:src="@drawable/background" />
    <ImageView
        Android:id="@+id/imageview2"
        Android:layout_centerInParent="true"
        Android:contentDescription="@string/desc"
        Android:layout_height="200dp"
        Android:layout_width="200dp" 
        Android:adjustViewBounds="true"
        Android:src="@drawable/image2" />
    <TextView
        Android:id="@+id/textview"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_centerHorizontal="true"
        Android:layout_below="@id/imageview2"
        Android:paddingLeft="8dp"
        Android:paddingRight="8dp"
        Android:gravity="center"
        Android:textSize="26sp"
        Android:textColor="#333"
        Android:background="#fff"
        Android:text="this is the text under the image right here"
        />
</RelativeLayout>
0
Scott Johansen