web-dev-qa-db-ja.com

ImageViewの幅に合わせて縦横比を維持するように画像を拡大縮小する

私はGridViewを持っています。 GridViewのデータはサーバからの要求です。

これがGridViewの項目レイアウトです。

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:background="@drawable/analysis_micon_bg"
    Android:gravity="center_horizontal"
    Android:orientation="vertical"
    Android:paddingBottom="@dimen/half_activity_vertical_margin"
    Android:paddingLeft="@dimen/half_activity_horizontal_margin"
    Android:paddingRight="@dimen/half_activity_horizontal_margin"
    Android:paddingTop="@dimen/half_activity_vertical_margin" >

    <ImageView
        Android:id="@+id/ranking_prod_pic"
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:adjustViewBounds="true"
        Android:contentDescription="@string/app_name"
        Android:scaleType="centerCrop" />

    <TextView
        Android:id="@+id/ranking_rank_num"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />

    <TextView
        Android:id="@+id/ranking_prod_num"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />

    <TextView
        Android:id="@+id/ranking_prod_name"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content" />
</LinearLayout>

サーバーにデータをリクエストし、画像のURLを取得してBitmapに画像をロードします

public static Bitmap loadBitmapFromInputStream(InputStream is) {
    return BitmapFactory.decodeStream(is);
}

public static Bitmap loadBitmapFromHttpUrl(String url) {
    try {
        return loadBitmapFromInputStream((InputStream) (new URL(url).getContent()));
    } catch (Exception e) {
        Log.e(TAG, e.getMessage());
        return null;
    }
}

そしてアダプタにgetView(int position, View convertView, ViewGroup parent)メソッドのコードがあります

Bitmap bitmap = BitmapUtil.loadBitmapFromHttpUrl(product.getHttpUrl());
prodImg.setImageBitmap(bitmap);

画像サイズは210*210です。 Nexus 4でアプリケーションを実行します。画像はImageViewの幅いっぱいに表示されますが、ImageViewの高さは拡大縮小されません。 ImageViewは画像全体を表示しません。

どうやってこの問題を解決しますか?

165
Joe

カスタムクラスやライブラリを使用しないでください。

<ImageView
    Android:id="@id/img"
    Android:layout_width="fill_parent"
    Android:layout_height="wrap_content"
    Android:adjustViewBounds="true"
    Android:scaleType="fitCenter" />

scaleType="fitCenter"(省略時のデフォルト)

  • 縦横比を維持しながら、必要に応じて親が許可する範囲で拡大または縮小します。

scaleType="centerInside"

  • srcの固有の幅が親の幅より小さい場合
    は画像を水平方向に中央揃えにします
  • srcの固有の幅が親の幅よりも大きい場合
    は、親が許す範囲で縦横比を縮小しながら、それを広くします。

Android:srcまたはImageView.setImage*メソッドを使用するかどうかは問題ではなく、おそらくキーはadjustViewBoundsです。

457
TWiStErRob

私はarnefmの答えが好きですが、彼は私が訂正しようとする小さなミスをしました(コメントを見てください):

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

/**
 * ImageView that keeps aspect ratio when scaled
 */
public class ScaleImageView extends ImageView {

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

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

  public ScaleImageView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  @Override
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    try {
      Drawable drawable = getDrawable();
      if (drawable == null) {
        setMeasuredDimension(0, 0);
      } else {
        int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
        int measuredHeight = MeasureSpec.getSize(heightMeasureSpec);
        if (measuredHeight == 0 && measuredWidth == 0) { //Height and width set to wrap_content
          setMeasuredDimension(measuredWidth, measuredHeight);
        } else if (measuredHeight == 0) { //Height set to wrap_content
          int width = measuredWidth;
          int height = width *  drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth();
          setMeasuredDimension(width, height);
        } else if (measuredWidth == 0){ //Width set to wrap_content
          int height = measuredHeight;
          int width = height * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight();
          setMeasuredDimension(width, height);
        } else { //Width and height are explicitly set (either to match_parent or to exact value)
          setMeasuredDimension(measuredWidth, measuredHeight);
        }
      }
    } catch (Exception e) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
  }

}

したがって、あなたのImageViewは適切に拡大縮小され、(例えば)ScrollViewの中に入れば、次元の問題はありません。

42
Alex Semeniuk

私は一度同様の問題を抱えていた。私はカスタムImageViewを作ることによってそれを解決しました。

public class CustomImageView extends ImageView

それからimageviewのonMeasureメソッドをオーバーライドします。私はこのようなことをしました。

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

        if (drawable == null) {
            setMeasuredDimension(0, 0);
        } else {
            float imageSideRatio = (float)drawable.getIntrinsicWidth() / (float)drawable.getIntrinsicHeight();
            float viewSideRatio = (float)MeasureSpec.getSize(widthMeasureSpec) / (float)MeasureSpec.getSize(heightMeasureSpec);
            if (imageSideRatio >= viewSideRatio) {
                // Image is wider than the display (ratio)
                int width = MeasureSpec.getSize(widthMeasureSpec);
                int height = (int)(width / imageSideRatio);
                setMeasuredDimension(width, height);
            } else {
                // Image is taller than the display (ratio)
                int height = MeasureSpec.getSize(heightMeasureSpec);
                int width = (int)(height * imageSideRatio);
                setMeasuredDimension(width, height);
            }
        }
    } catch (Exception e) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

これはアスペクト比を維持しながら画像をスクリーンに合うように引き伸ばします。

36
arnefm

Android:scaleType="centerCrop"を使用してください。

20
Mark Buikema

私は上記と同じようなことをしました、そしてそれがRelativeLayoutの中ではうまくいかなかったので数時間の間壁に頭をぶつけました。私は次のようなコードになった。

package com.example;

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

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

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

        if (d != null) {
            int width;
            int height;
            if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) {
                height = MeasureSpec.getSize(heightMeasureSpec);
                width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight());
            } else {
                width = MeasureSpec.getSize(widthMeasureSpec);
                height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth());
            }
            setMeasuredDimension(width, height);
        } else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}

そしてRelativeLayoutが測定された寸法を無視しないようにするために、私はこれをしました:

    <FrameLayout
        Android:id="@+id/image_frame"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"
        Android:layout_alignParentLeft="true"
        Android:layout_below="@+id/something">

        <com.example.ScaledImageView
            Android:id="@+id/image"
            Android:layout_width="wrap_content"
            Android:layout_height="150dp"/>
    </FrameLayout>
9
Dave Cole

ImageViewで背景として画像を設定する場合、これは適用されません、srcに設定する必要があります(Android:src)。

ありがとう。

4
Guna Sekhar

これを試してください:それは私のための問題を解決しました

   Android:adjustViewBounds="true"
    Android:scaleType="fitXY"
4

Javaコードは必要ありません。あなたがする必要があります:

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

幅と高さの一致する親にキーがあります

3
Romu Dizzy

縦横比を維持するためにImageViewでこれらのプロパティを使います:

Android:adjustViewBounds="true"
Android:scaleType="fitXY"
2
Atif Mahmood

あなたは手動で画像をロードすることによってあなたがしていることを試みることができます、しかし私は非常に非常に強く Universal Image Loader を見ることを勧めます。

私は最近それを私のプロジェクトに統合しました、そしてそれは素晴らしいと言わなければなりません。非同期化、サイズ変更、画像のキャッシュを心配していませんか。統合とセットアップは本当に簡単です。 5分以内にあなたはおそらくあなたが望むことをやってもらうことができます。

コード例:

//ImageLoader config
DisplayImageOptions displayimageOptions = new DisplayImageOptions.Builder().showStubImage(R.drawable.downloadplaceholder).cacheInMemory().cacheOnDisc().showImageOnFail(R.drawable.loading).build();

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()).
            defaultDisplayImageOptions(displayimageOptions).memoryCache(new WeakMemoryCache()).discCache(new UnlimitedDiscCache(cacheDir)).build();

    if (ImageLoader.getInstance().isInited()) {
        ImageLoader.getInstance().destroy();
    }
    ImageLoader.getInstance().init(config);

    imageLoadingListener = new ImageLoadingListener() {
        @Override
        public void onLoadingStarted(String s, View view) {

        }

        @Override
        public void onLoadingFailed(String s, View view, FailReason failReason) {
            ImageView imageView = (ImageView) view;
            imageView.setImageResource(R.drawable.Android);
            Log.i("Failed to Load " + s, failReason.toString());
        }

        @Override
        public void onLoadingComplete(String s, View view, Bitmap bitmap) {

        }

        @Override
        public void onLoadingCancelled(String s, View view) {

        }
    };

//Imageloader usage
ImageView imageView = new ImageView(getApplicationContext());
    if (orientation == 1) {
        imageView.setLayoutParams(new LinearLayout.LayoutParams(width / 6, width / 6));
    } else {
        imageView.setLayoutParams(new LinearLayout.LayoutParams(height / 6, height / 6));
    }
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageLoader.displayImage(SERVER_HOSTNAME + "demos" + demo.getPathRoot() + demo.getRootName() + ".png", imageView, imageLoadingListener);

これは画像を遅延ロードし、ロード中はプレースホルダ画像を表示し、ロードが失敗してリソースをキャッシュした場合はデフォルトアイコンを表示するimageViewのサイズに正しく合わせることができます。

- この現在の設定は画像の縦横比を保持しているので、元の質問にも当てはまります。

1
o0rebelious0o

幅が画面の幅と等しく、縦横比に応じて高さが比例して設定された画像を作成するには、次の手順を実行します。

Glide.with(context).load(url).asBitmap().into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {

                        // creating the image that maintain aspect ratio with width of image is set to screenwidth.
                        int width = imageView.getMeasuredWidth();
                        int diw = resource.getWidth();
                        if (diw > 0) {
                            int height = 0;
                            height = width * resource.getHeight() / diw;
                            resource = Bitmap.createScaledBitmap(resource, width, height, false);
                        }
                                              imageView.setImageBitmap(resource);
                    }
                });

お役に立てれば。

1
Fathima km

この単純な行を試してみてください...依存関係を追加することなく、画像表示タグのxmlコードにこの行を追加します。Android:scaleType = "fitXY"

1
ziddi609

UniversalImageLoaderを使用して設定するだけです。

DisplayImageOptions.Builder()
    .imageScaleType(ImageScaleType.EXACTLY_STRETCHED)
    .build();

とImageViewのスケール設定なし

0
Artem

使いやすいピカソを使用してください。

あなたのアダプタで..

@Override
public void getView(int position, View convertView, ViewGroup parent) {

 ImageView view = (ImageView) convertView.findViewById(R.id.ranking_prod_pic);

 Picasso.with(context).load(url).into(view); //url is image url

 //you can resize image if you want

 /* Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(view) */

}

http://square.github.io/picasso/ enter image description here

0
chiragkyada

androidを使用:ScaleType = "fitXY" im ImageView xml

0
Naveed Naeem