How to fit an image of random size to an ImageView?
When:

  • 最初ImageView个尺寸为250dp*250dp
  • 图像的较大尺寸应放大/缩小至250dp
  • 图像应保持其纵横比
  • zoom 后,ImageView个尺寸应与zoom 图像的尺寸匹配

E.g. for an image of 100*150, the image and the ImageView should be 166*250.
E.g. for an image of 150*100, the image and the ImageView should be 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.

推荐答案

(The answer was heavily modified after clarifications to the original question)

After clarifications:
This cannot be done in xml only. It is not possible to scale both the image and the ImageView so that image's one dimension would always be 250dp and the ImageView would have the same dimensions as the image.

ImageViewThis code scales Drawable保持在一个250dp x 250dp的正方形中,一维正好为250dp,并保持纵横比.然后调整ImageView的大小以匹配zoom 图像的尺寸.代码用于活动中.我通过按钮点击处理程序测试了它.

Enjoy. :)

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"/>


Thanks to this discussion for the scaling code:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html


UPDATE 7th, November 2012:
Added null pointer check as suggested in comments

Android相关问答推荐

如何使用喷气背包压缩让Animated Image Vector每次动画化一条路径?

CameraX与jetpack组成屏幕逻辑

在Android Studio Iguana 2023.2.1中,哪里可以找到能量分析器?

为什么R8不混淆某些类?

无法列出目录中的文件'

Jetapck Compose:将Compose BOM更新为最新版本&2024.01.00&Quot;CircularProgressIndicator后出现错误

在Android Studio中,如何在BuildSrc Dependenices Kotlin文件中指定时标记与旧版本的依赖关系

Modifer.Align()不适用于行/列/框中的文本.未解决的作用域实例错误

从不可组合回调打开可组合屏幕

如何在 compose 中使用可变对象?

面向Jetpack Compose的可组合放置问题

Jetpack Compose 中的用户在线指示器

如何使用滑行加载媒体的专辑封面?

如何在ExecutorService中设置progressBar的进度?不想使用 AsyncTask,因为它已被弃用

Jetpack Compose 绘制范围内的动画

无法通过 retrofit 解析对 kotlin 数据类的 xml 响应

GridLayout 和 GridView 有什么好用和区别

Android 12 通过包管理器中断 APK 安装?

Android YouTube SDK - 视频无法在某些 Android 设备中播放

如何获取 Material Design 3 的底部导航栏高度?