web-dev-qa-db-fra.com

ImageView adjustViewBounds ne fonctionne pas

J'ai un ImageView avec Android:layout_width=100dp, Android:layout_height=wrap_content et Android:adjustViewBounds=true

Sa source est une image de 50 x 50 px. Mais le rapport hauteur/largeur n’est pas préservé - la hauteur de ImageView est 50 pixels, pas 100 pixels (c’est-à-dire que adjustViewBounds ne fonctionne pas). Si j'ai une image de 200x200px cela fonctionne - la largeur et la hauteur sont 100px. Ce code donne une image de 100 pixels de large et 50 pixels de haut, mais l’image src est carrée:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent">

    <ImageView
        Android:id="@+id/photo"
        Android:src="@drawable/icon"
        Android:layout_width="100dp"
        Android:layout_height="wrap_content"
        Android:scaleType="fitXY"
        Android:adjustViewBounds="true" />

</LinearLayout>
36
fhucho

Le problème est que adjustViewBoundsn'augmentera pas la taille de ImageView au-delà des dimensions naturelles du dessinable. Il ne fera que réduire la vue pour conserver les proportions; si vous fournissez une image 500x500 au lieu d'une image 50x50, cela devrait fonctionner.

Si vous êtes intéressé par l'endroit où ce comportement est implémenté, voir Implémentation onMeasure de ImageView.Java .

Une solution de contournement consiste à implémenter une ImageView personnalisée qui modifie ce comportement dans onMeasure.

65
Roman Nurik

Il y a un moyen plus simple. Faites votre ImageView comme ceci:

<ImageView
  Android:layout_width="match_parent"
  Android:layout_height="match_parent"
  Android:scaleType="fitCenter"
  Android:adjustViewBounds="true"/>

De cette façon, dessinable s’étira pour s’adapter au centre de la vue Image en conservant Le format de l’image. Nous devons juste calculer la bonne hauteur pour la rendre proportionnelle. Donc, nous n'avons pas d'espace vide:

private void setImageBitmap(Bitmap bitmap, ImageView imageView){
    float i = ((float)imageWidth)/((float)bitmap.getWidth());
    float imageHeight = i * (bitmap.getHeight());
    imageView.setLayoutParams(new RelativeLayout.LayoutParams(imageWidth, (int) imageHeight));
    imageView.setImageBitmap(bitmap);
}
11
vladexologija

En plus de @ RomanNurik's answer

Vous pouvez trouver une solution de travail ici , soit copier du code ou simplement ajouter la dépendance de Gradle

dependencies {
    compile 'com.inthecheesefactory.thecheeselibrary:adjustable-imageview:1.0.1'
}

P.S. La solution fournie par @Nilzor n'a pas fonctionné pour moi

2
duviteck

J'ai eu une exigence similaire; Dans mon cas, je voulais que l'image soit carrée et que ImageView corresponde au rapport de format afin que je puisse utiliser son arrière-plan et son remplissage pour tracer une bordure.

J'ai lu les réponses ici, mais au lieu de remplacer ImageView, j'ai décidé de faire une mise en page qui garantisse que son contenu (ne devrait contenir qu'une seule vue) est carré. De cette façon, je pourrais utiliser un ImageView standard à l'intérieur. (Et vous ne savez jamais, je pourrais vouloir faire autre chose plus tard. Bien que probablement pas.)

Au cas où cela serait utile pour quelqu'un d'autre, voici le code (n'hésitez pas à le copier). Il y a probablement des bugs car je viens de le faire fonctionner pour mon application, puis arrêté. :)

public class SquareLayout extends ViewGroup
{
    public SquareLayout(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }

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

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

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        // Work out width and height, and square size.
        int width = r - l;
        int height = b - t;

        int size, xOffset, yOffset;
        if(width < height)
        {
            size = width;
            xOffset = 0;
            yOffset = (height - size) / 2;
        }
        else
        {
            size = height;
            xOffset = (width - size) / 2;
            yOffset = 0;
        }

        for(int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            child.layout(xOffset, yOffset, size + xOffset, size + yOffset);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        // Get width and height.
        int w = -1, h = -1;
        switch(MeasureSpec.getMode(widthMeasureSpec))
        {
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            w = MeasureSpec.getSize(widthMeasureSpec);
            break;

        case MeasureSpec.UNSPECIFIED:
            break;
        }
        switch(MeasureSpec.getMode(heightMeasureSpec))
        {
        case MeasureSpec.AT_MOST:
        case MeasureSpec.EXACTLY:
            h = MeasureSpec.getSize(heightMeasureSpec);
            break;

        case MeasureSpec.UNSPECIFIED:
            break;
        }

        // If only one of width/height is unspecified, set them both the same.
        if(w == -1 && h != -1)
        {
            w = h;
        }
        else if(h == -1 && w != -1)
        {
            h = w;
        }

        // Either they're both specified or both unspecified.
        int childMeasureSpec;
        if(w == -1)
        {
            childMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        else
        {
            childMeasureSpec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY);
        }

        // Pass through to children.
        int maxDimension = 1;
        for(int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            child.measure(childMeasureSpec, childMeasureSpec);
            maxDimension = Math.max(maxDimension, child.getMeasuredWidth());
            maxDimension = Math.max(maxDimension, child.getMeasuredHeight());
        }

        if(w == -1)
        {
            w = maxDimension;
            h = maxDimension;
        }

        setMeasuredDimension(w, h);
    }
}
0
sam