62 votes

Android ImageView ajustant la hauteur du parent et la largeur d'adaptation

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

Je suis un peu bloqué par ce problème qui, je pense, devrait être assez simple.

Mon application télécharge donc une image et rend le bitmap dans une ImageView, un élément enfant d'un RelativeLayout. J'aimerais que l'ImageView s'adapte à la largeur de l'élément parent et que sa taille soit adaptée pour conserver le rapport d'aspect.

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

    }

Désiré :

Desired result

Résultat :

Current result

147voto

Serafim S. Points 1054

Merci à @Julien et @js. Voici la solution complète d'ImageView qui va étirer la hauteur du bitmap en préservant le ratio d'aspect même si le bitmap est plus petit 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 de ImageView.

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

51voto

Matthew Willis Points 26453

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

8voto

Julien Points 3525

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

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

    }

2voto

2bard Points 1517

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

Vous devez modifier le type d'échelle en imgV.setScaleType(ImageView.ScaleType.CENTER_INSIDE) ;

2voto

chuz Points 157

J'ai apporté une légère modification à la solution de @Seraphim S pour tenir compte des cas où l'image peut être large, et les limites de la vue également larges (par exemple, en tournant 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);
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X