web-dev-qa-db-fra.com

Android ImageView ajustant la hauteur du parent et la largeur

Mise à jour : J'ai résolu ce problème en utilisant la méthode décrite dans cette réponse

Je suis un peu coincé avec cette question, qui, à mon avis, devrait être assez simple.

Donc, mon application télécharge une image et rend le bitmap dans un ImageView, un élément enfant de RelativeLayout. J'aimerais que ImageView corresponde à la largeur du parent et que sa taille soit adaptée pour conserver le rapport hauteur/largeur.

Voici mon XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
>
<RelativeLayout Android:id="@+id/banner" Android:layout_width="fill_parent" Android:layout_height="wrap_content"></RelativeLayout>
<TextView  
Android:layout_width="fill_parent" 
Android:layout_height="wrap_content" 
Android:text="@string/hello"
/>
</LinearLayout>

Et le code:

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


    RelativeLayout banner = (RelativeLayout) findViewById(R.id.banner);
    ImageView imgV = new ImageView(this);

    imgV.setScaleType(ImageView.ScaleType.CENTER_CROP);
    // I tried all the scale types : CENTER_INSIDE : same effect, FIT_CENTER : same effect... 

    imgV.setBackgroundColor(0x00FFFF00);

    imgV.setAdjustViewBounds(Color.BLUE);


    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);

    banner.addView(imgV,params);

    // Some code downloading the image stream

    bitmap = BitmapFactory.decodeStream(stream);


    imgV.setImageBitmap(bitmap);

    }

souhaité:

Desired result

Résultat:

Current result

62
Julien

Merci à @ Julien et à @ js. Voici une solution complète d’ImageView qui étendra la hauteur des images bitmap en préservant les proportions, même si l’image bitmap est plus petite que ImageView.

public class ResizableImageView extends ImageView {

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

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
         Drawable d = getDrawable();

         if(d!=null){
                 // ceil not round - avoid thin vertical gaps along the left/right edges
                 int width = MeasureSpec.getSize(widthMeasureSpec);
                 int height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
                 setMeasuredDimension(width, height);
         }else{
                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
    }

}

Vous pouvez utiliser cette classe dans vos mises en page XML à la place ImageView.

<com.example.ResizableImageView
    Android:id="@+id/banner"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:src="@drawable/banner" />
146
Serafim Suhenky

Vous recherchez probablement Android:adjustViewBounds="true" En xml ou imageView.setAdjustViewBounds(true) en Java.

51
Matthew Willis

Comme je l'ai mentionné dans un commentaire, j'ai sous-classé ImageView. J'ai trouvé mon code, voila:

    protected class ResizableImageView extends ImageView
    {

        private Bitmap mBitmap;

        // Constructor

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


        // Overriden methods


          @Override 
          protected void onMeasure(int widthMeasureSpec,
                  int heightMeasureSpec) {
              if(mBitmap != null)
              {
                    int width = MeasureSpec.getSize(widthMeasureSpec);
                    int height = width * mBitmap.getHeight() / mBitmap.getWidth();
                    setMeasuredDimension(width, height);

              } 
              else
              {
                  super.onMeasure(widthMeasureSpec,
                          heightMeasureSpec);
              }
              }

            @Override
            public void setImageBitmap(Bitmap bitmap)
            {
                mBitmap = bitmap;
                 super.setImageBitmap(bitmap);
            }

    }
8
Julien

J'ai légèrement modifié la solution de @Seraphim S afin de prendre en compte les cas où l'image peut être large et les limites de la vue également étendues (par exemple, faire pivoter l'appareil en mode paysage).

public class ResizableImageView extends ImageView {
    public ResizableImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Drawable d = getDrawable();

        if (d != null) {

            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = MeasureSpec.getSize(heightMeasureSpec);

            if (width >= height) {
                width = (int) Math.ceil((float) height * (float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight());
            } else {
                height = (int) Math.ceil((float) width * (float) d.getIntrinsicHeight() / (float) d.getIntrinsicWidth());
            }

            setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}
2
chuz

Je pense que vous devriez changer votre largeur imgV en "match_parent"

Vous devez changer le type de balance en imgV.setScaleType (ImageView.ScaleType.CENTER_INSIDE);

2
2bard