将图像调整为ImageView,保持宽高比,然后将ImageView调整为图像尺寸?

如何将随机大小的图像适合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。

(在对原始问题进行澄清之后,答案已经有了很大的修改)

澄清之后:
不能在xml中完成 。 无法缩放图像和ImageView因此图像的一个维度总是250dp,而ImageView的维度与图像维度相同。

这段代码ImageViewDrawable 比例保持为250dp x 250dp的正方形,一维恰好为250dp并保持纵横比。 然后调整ImageView的大小以匹配缩放图像的尺寸。 该代码在一个活动中使用。 我通过button点击处理程序testing它。

请享用。 🙂

 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日:
注释中build议添加空指针检查

可能不是这个具体问题的答案,但如果像我这样的人,寻找答案如何在保留长宽比的ImageView中以有限大小(例如, maxWidth )适合图像,然后摆脱ImageView占用的过多空间,那么最简单的解决scheme是在XML中使用以下属性:

  android:scaleType="centerInside" android:adjustViewBounds="true" 
 <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:adjustViewBounds="true"/> 

下面的代码完全使用相同大小的图像视图。 获取位图图像的高度和宽度,然后借助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) 

请享用。

尝试添加android:scaleType="fitXY"到您的ImageView

search了一天后,我认为这是最简单的解决scheme:

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

编辑雅诺Argillanders回答:

如何用你的宽度和高度来适应图像:

1)初始化ImageView并设置Image:

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

2)现在resize:

 scaleImage(iv); 

编辑的scaleImage方法:( 可以replaceEXPECTED的边界值

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

使用此代码:

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

这一切都可以使用XML来完成…其他方法似乎相当复杂。 无论如何,你只需将高度设置为你想要的高度,然后设置宽度来包装内容,反之亦然。 使用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"> 

这是为我的情况做的。

  <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:scaleType="centerCrop" android:adjustViewBounds="true" /> 

我需要用毕加索的约束布局完成这个工作,所以我把上面的一些答案拼凑在一起,并提出了这个解决scheme(我已经知道了我加载的图像的纵横比,所以帮助):

在我的activity代码中调用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> 

注意缺less一个constraintBottom_toBottomOf属性。 ImageLoader是我自己的图像加载util方法和常量的静态类。

我需要有一个ImageView和一个位图,所以位图缩放到ImageView的大小,ImageView的大小是缩放的位图的相同:)。

我正在通过这个post看如何去做,最后做了我想要的,而不是这里描述的方式。

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

结果是图像完美地融合在一起,保持宽高比,并且在Bitmap内部没有来自ImageView的额外的剩余像素。

结果

重要的ImageView有wrap_content和adjustViewBounds为true,然后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. */