web-dev-qa-db-ja.com

ImageViewに画像をフィットさせ、アスペクト比を保ち、そしてImageViewをimageの寸法にリサイズしますか?

ランダムサイズの画像をImageViewに合わせるにはどうすればいいですか?
いつ:

  • 当初ImageViewの寸法は250dp * 250dpです。
  • 画像の大きい方のサイズは250dpに拡大/縮小する必要があります
  • 画像は縦横比を維持する必要があります
  • ImageViewのサイズは、拡大縮小後に拡大縮小された画像のサイズと一致する必要があります

例えば。 100 * 150の画像の場合、画像とImageViewは166 * 250になります。
例えば。 150 * 100の画像の場合、画像とImageViewは250 * 166になります。

境界を次のように設定すると

<ImageView
    Android:id="@+id/picture"
    Android:layout_width="250dp"
    Android:layout_height="250dp"
    Android:layout_gravity="center_horizontal"
    Android:layout_marginTop="20dp"
    Android:adjustViewBounds="true" />

画像はImageViewに正しく収まりますが、ImageViewは常に250dp * 250dpです。

149
jul

(元の質問を明確にした後、回答が大幅に変更されました)

説明の後:
これはxmlのみではできません。 imageとImageViewの両方を拡大縮小して、imageの1つの寸法が常に250dpになり、ImageViewがimageと同じ寸法になるようにすることはできません。

このコードは、DrawableImageViewを、縦横比を保ちながら1次元が250dp x 250dpのような正方形に収まるように拡大縮小します。それからImageViewは拡大縮小されたイメージの寸法に合うようにサイズ変更されます。コードはアクティビティで使用されます。ボタンクリックハンドラでテストしました。

お楽しみください。 :)

private void scaleImage(ImageView view) throws NoSuchElementException  {
    // Get bitmap from the the ImageView.
    Bitmap bitmap = null;

    try {
        Drawable drawing = view.getDrawable();
        bitmap = ((BitmapDrawable) drawing).getBitmap();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("No drawable on given view");
    } catch (ClassCastException e) {
        // Check bitmap is Ion drawable
        bitmap = Ion.with(view).getBitmap();
    }

    // Get current dimensions AND the desired bounding box
    int width = 0;

    try {
        width = bitmap.getWidth();
    } catch (NullPointerException e) {
        throw new NoSuchElementException("Can't find bitmap on given view/drawable");
    }

    int height = bitmap.getHeight();
    int bounding = dpToPx(250);
    Log.i("Test", "original width = " + Integer.toString(width));
    Log.i("Test", "original height = " + Integer.toString(height));
    Log.i("Test", "bounding = " + Integer.toString(bounding));

    // Determine how much to scale: the dimension requiring less scaling is
    // closer to the its side. This way the image always stays inside your
    // bounding box AND either x/y axis touches it.  
    float xScale = ((float) bounding) / width;
    float yScale = ((float) bounding) / height;
    float scale = (xScale <= yScale) ? xScale : yScale;
    Log.i("Test", "xScale = " + Float.toString(xScale));
    Log.i("Test", "yScale = " + Float.toString(yScale));
    Log.i("Test", "scale = " + Float.toString(scale));

    // Create a matrix for the scaling and add the scaling data
    Matrix matrix = new Matrix();
    matrix.postScale(scale, scale);

    // Create a new bitmap and convert it to a format understood by the ImageView 
    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth(); // re-use
    height = scaledBitmap.getHeight(); // re-use
    BitmapDrawable result = new BitmapDrawable(scaledBitmap);
    Log.i("Test", "scaled width = " + Integer.toString(width));
    Log.i("Test", "scaled height = " + Integer.toString(height));

    // Apply the scaled bitmap
    view.setImageDrawable(result);

    // Now change ImageView's dimensions to match the scaled image
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);

    Log.i("Test", "done");
}

private int dpToPx(int dp) {
    float density = getApplicationContext().getResources().getDisplayMetrics().density;
    return Math.round((float)dp * density);
}

ImageViewのxmlコード:

<ImageView a:id="@+id/image_box"
    a:background="#ff0000"
    a:src="@drawable/star"
    a:layout_width="wrap_content"
    a:layout_height="wrap_content"
    a:layout_marginTop="20dp"
    a:layout_gravity="center_horizontal"/>


スケーリングコードについてのこの議論のおかげで:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html


更新2012年11月7日:
コメントで示唆されているようにnullポインタチェックを追加しました

131

この特定の質問に対する回答ではないかもしれませんが、私のように、縦横比を維持しながらImageViewに画像を収まるサイズ(たとえばmaxWidth)にし、ImageViewによって占有される過剰なスペースを取り除く方法を探している場合は、最も簡単な解決策は、XMLで次のプロパティを使用することです。

    Android:scaleType="centerInside"
    Android:adjustViewBounds="true"
204
Sarge Borsch
<ImageView Android:layout_width="match_parent"
           Android:layout_height="wrap_content"
           Android:scaleType="centerCrop"
           Android:adjustViewBounds="true"/>
39
diesel

以下のコードは、同じサイズのimageviewでビットマップを完全に作ります。ビットマップ画像の高さと幅を取得してから、imageviewのパラメータを使用して新しい高さと幅を計算します。それはあなたが最高の縦横比を持つ必要な画像を与える。

int currentBitmapWidth = bitMap.getWidth();
int currentBitmapHeight = bitMap.getHeight();

int ivWidth = imageView.getWidth();
int ivHeight = imageView.getHeight();
int newWidth = ivWidth;

newHeight = (int) Math.floor((double) currentBitmapHeight *( (double) new_width / (double) currentBitmapWidth));

Bitmap newbitMap = Bitmap.createScaledBitmap(bitMap, newWidth, newHeight, true);

imageView.setImageBitmap(newbitMap)

楽しい。

21
Naresh Sharma

ImageViewAndroid:scaleType="fitXY"を追加してみてください。

12
DeeFour

一日を検索した後、私はこれが最も簡単な解決策だと思います:

imageView.getLayoutParams().width = 250;
imageView.getLayoutParams().height = 250;
imageView.setAdjustViewBounds(true);
7
MikeyB

ほとんどの場合に有効な最善の解決策は、

これが一例です。

<ImageView Android:id="@+id/avatar"
           Android:layout_width="match_parent"
           Android:layout_height="match_parent"
           Android:scaleType="fitXY"/>
5

これはすべてXMLを使用して実行できます。他の方法はかなり複雑に見えます。とにかく、あなたはただあなたがdpであなたが望むものに高さを設定して、それからコンテンツをラップするために幅を設定するか、あるいはその逆になります。画像のサイズを調整するには、scaleType fitCenterを使用してください。

<ImageView
    Android:layout_height="200dp"
    Android:layout_width="wrap_content"
    Android:scaleType="fitCenter"
    Android:adjustViewBounds="true"
    Android:src="@mipmap/ic_launcher"
    Android:layout_below="@+id/title"
    Android:layout_margin="5dip"
    Android:id="@+id/imageView1">
5
Thunderstick

このコードを使用してください:

<ImageView Android:id="@+id/avatar"
           Android:layout_width="fill_parent"
           Android:layout_height="match_parent"
           Android:scaleType="fitXY" />
4
Abhay Anand

編集Jarno Argillanders答え:

画像を幅と高さに合わせる方法:

1)ImageViewを初期化してImageを設定します。

iv = (ImageView) findViewById(R.id.iv_image);
iv.setImageBitmap(image);

2)今サイズ変更:

scaleImage(iv);

scaleImageメソッドを編集しました:(あなたは期待された境界値を置き換えることができます

private void scaleImage(ImageView view) {
    Drawable drawing = view.getDrawable();
    if (drawing == null) {
        return;
    }
    Bitmap bitmap = ((BitmapDrawable) drawing).getBitmap();

    int width = bitmap.getWidth();
    int height = bitmap.getHeight();
    int xBounding = ((View) view.getParent()).getWidth();//EXPECTED WIDTH
    int yBounding = ((View) view.getParent()).getHeight();//EXPECTED HEIGHT

    float xScale = ((float) xBounding) / width;
    float yScale = ((float) yBounding) / height;

    Matrix matrix = new Matrix();
    matrix.postScale(xScale, yScale);

    Bitmap scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
    width = scaledBitmap.getWidth();
    height = scaledBitmap.getHeight();
    BitmapDrawable result = new BitmapDrawable(context.getResources(), scaledBitmap);

    view.setImageDrawable(result);

    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); 
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);
}

そして.xml:

<ImageView
    Android:id="@+id/iv_image"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_gravity="center_horizontal" />
4
Volodymyr Kulyk

これは私の場合はそうでした。

             <ImageView
                Android:layout_width="match_parent"
                Android:layout_height="wrap_content"
                Android:layout_centerHorizontal="true"
                Android:scaleType="centerCrop"
                Android:adjustViewBounds="true"
                />
3
Ronny Kibet

私はImageViewとBitmapを持っている必要があったので、BitmapはImageViewサイズに合わせて拡大縮小され、ImageViewのサイズは拡大縮小されたBitmap :)と同じです。

私はそれをどのように行うかについてこの記事を通して調べていて、そして最後に私が欲しいものをしました、しかしここで説明された方法ではありません。

<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/acpt_frag_root"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:background="@color/imageBackground"
Android:orientation="vertical">

<ImageView
    Android:id="@+id/acpt_image"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    Android:layout_gravity="center"
    Android:adjustViewBounds="true"
    Android:layout_margin="@dimen/document_editor_image_margin"
    Android:background="@color/imageBackground"
    Android:elevation="@dimen/document_image_elevation" />

そしてonCreateViewメソッドで

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_scanner_acpt, null);

    progress = view.findViewById(R.id.progress);

    imageView = view.findViewById(R.id.acpt_image);
    imageView.setImageBitmap( bitmap );

    imageView.getViewTreeObserver().addOnGlobalLayoutListener(()->
        layoutImageView()
    );

    return view;
}

そして次にlayoutImageView()コード

private void layoutImageView(){

    float[] matrixv = new float[ 9 ];

    imageView.getImageMatrix().getValues(matrixv);

    int w = (int) ( matrixv[Matrix.MSCALE_X] * bitmap.getWidth() );
    int h = (int) ( matrixv[Matrix.MSCALE_Y] * bitmap.getHeight() );

    imageView.setMaxHeight(h);
    imageView.setMaxWidth(w);

}

その結果、縦横比を保ちながら画像が完全に収まり、ビットマップが内側にあるときにImageViewから余計なピクセルが残りません。

結果

Wrap_contentとadjustViewBoundsをtrueにすることはImageViewにとって重要です。それからsetMaxWidthとsetMaxHeightは動作します。これはImageViewのソースコードで書かれています、

/*An optional argument to supply a maximum height for this view. Only valid if
 * {@link #setAdjustViewBounds(boolean)} has been set to true. To set an image to be a
 * maximum of 100 x 100 while preserving the original aspect ratio, do the following: 1) set
 * adjustViewBounds to true 2) set maxWidth and maxHeight to 100 3) set the height and width
 * layout params to WRAP_CONTENT. */
1
alekshandru

単純な数学を使用して画像のサイズを変更します。 ImageViewのサイズを変更できるか、ImageViewに設定されているよりも描画可能なイメージのサイズを変更できます。 ImageViewに設定するビットマップの幅と高さを見つけて、目的のメソッドを呼び出します。幅500がメソッドの呼び出しよりも高さより大きいと仮定します

//250 is the width you want after resize bitmap
Bitmat bmp = BitmapScaler.scaleToFitWidth(bitmap, 250) ;
ImageView image = (ImageView) findViewById(R.id.picture);
image.setImageBitmap(bmp);

ビットマップのサイズ変更にこのクラスを使用します。

public class BitmapScaler{
// Scale and maintain aspect ratio given a desired width
// BitmapScaler.scaleToFitWidth(bitmap, 100);
 public static Bitmap scaleToFitWidth(Bitmap b, int width)
  {
    float factor = width / (float) b.getWidth();
    return Bitmap.createScaledBitmap(b, width, (int) (b.getHeight() * factor), true);
  }


  // Scale and maintain aspect ratio given a desired height
  // BitmapScaler.scaleToFitHeight(bitmap, 100);
  public static Bitmap scaleToFitHeight(Bitmap b, int height)
  {
    float factor = height / (float) b.getHeight();
    return Bitmap.createScaledBitmap(b, (int) (b.getWidth() * factor), height, true);
   }
 }

xmlコードは

<ImageView
Android:id="@+id/picture"
Android:layout_width="250dp"
Android:layout_height="250dp"
Android:layout_gravity="center_horizontal"
Android:layout_marginTop="20dp"
Android:adjustViewBounds="true"
Android:scaleType="fitcenter" />
0
Ritesh Namdev

Picassoを使用してこれを制約レイアウトで実行する必要があったので、上記の回答をいくつかまとめてこの解決策を思いつきました(ロードした画像の縦横比はすでにわかっているので、役に立ちます)。

setContentView(...)の後のどこかに自分のアクティビティコードで呼ばれます

protected void setBoxshotBackgroundImage() {
    ImageView backgroundImageView = (ImageView) findViewById(R.id.background_image_view);

    if(backgroundImageView != null) {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        int width = displayMetrics.widthPixels;
        int height = (int) Math.round(width * ImageLoader.BOXART_HEIGHT_ASPECT_RATIO);

        // we adjust the height of this element, as the width is already pinned to the parent in xml
        backgroundImageView.getLayoutParams().height = height;

        // implement your Picasso loading code here
    } else {
        // fallback if no element in layout...
    }
}

私のXMLでは

<?xml version="1.0" encoding="utf-8"?>

<Android.support.constraint.ConstraintLayout
xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools"
xmlns:app="http://schemas.Android.com/apk/res-auto"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
tools:layout_editor_absoluteY="0dp"
tools:layout_editor_absoluteX="0dp">

    <ImageView
        Android:id="@+id/background_image_view"
        Android:layout_width="0dp"
        Android:layout_height="0dp"
        Android:scaleType="fitStart"
        app:srcCompat="@color/background"
        Android:adjustViewBounds="true"
        tools:layout_editor_absoluteY="0dp"
        Android:layout_marginTop="0dp"
        Android:layout_marginBottom="0dp"
        Android:layout_marginRight="0dp"
        Android:layout_marginLeft="0dp"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <!-- other elements of this layout here... -->

</Android.support.constraint.ConstraintLayout>

ConstraintBottom_toBottomOf属性がないことに注意してください。 ImageLoaderはutilメソッドや定数をロードするための私自身の静的クラスです。

0
the_dude_abides

私は非常に単純な解決策を使っています。ここに私のコード:

imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.MATCH_PARENT));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.getLayoutParams().height = imageView.getLayoutParams().width;
imageView.setMinimumHeight(imageView.getLayoutParams().width);

私の写真はgridviewに動的に追加されます。 imageviewにこれらの設定をするとき、絵は自動的に1:1の比率で表示されることができます。

0
Bilal Demir