Android ImageView可缩小图像到宽度,灵活高度,而不会裁剪或变形

经常问,从来没有回答(至less不能以可重现的方式)。

我有一个图像视图与比视图的图像。 我想缩放图像到屏幕的宽度,并调整ImageView的高度以反映图像的比例正确的高度。

<ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" /> 

这导致图像以其原始尺寸居中(小于屏幕宽度),并在边上留有边缘。 不好。

所以我补充说

 android:adjustViewBounds="true" 

同样的效果,不好。 我补充说

 android:scaleType="centerInside" 

同样的效果,不好。 我改变了centerInsidefitCenter 。 同样的效果,不好。 我把中心centerInsidecenterCrop

 android:scaleType="centerCrop" 

现在,最后,图像缩放到屏幕的宽度 – 但在顶部和底部裁剪 ! 所以我改变了centerCropfitXY

 android:scaleType="fitXY" 

现在图像被缩放到屏幕的宽度,但不在 y轴上缩放,导致图像失真

删除android:adjustViewBounds="true"没有效果。 正如其他地方所build议的,添加一个android:layout_gravity ,再次没有效果。

我尝试了其他组合 – 无济于事。 所以,请有人知道:

如何设置ImageView的XML以填充屏幕的宽度,缩放较小的图像以填充整个视图,以不变形或裁剪的方式显示图像的高宽比?

编辑:我也尝试设置任意数字高度。 这只与centerCrop设置有关。 它将根据视图高度垂直变形图像。

我已经通过创build一个包含在布局文件中的java类来解决这个问题:

 public class DynamicImageView extends ImageView { public DynamicImageView(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin vertical gaps along the left/right edges final int width = MeasureSpec.getSize(widthMeasureSpec); final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

现在,通过将您的类添加到布局文件中来使用它:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <my.package.name.DynamicImageView android:layout_width="fill_parent" android:layout_height="wrap_content" android:scaleType="centerCrop" android:src="@drawable/about_image" /> </RelativeLayout> 

我有和你一样的问题。 经过30分钟的尝试diffirent变化我解决了这个问题。 它给你灵活的高度宽度调整到父宽度

 <ImageView android:id="@+id/imageview_company_logo" android:layout_width="fill_parent" android:layout_height="fill_parent" android:adjustViewBounds="true" android:scaleType="fitCenter" android:src="@drawable/appicon" /> 

XML布局标准中没有可行的解决scheme。

对dynamic图像大小作出反应的唯一可靠方法是在代码中使用LayoutParams

令人失望。

  android:scaleType="fitCenter" 

计算一个将保持原始src宽高比的比例,但也将确保src完全适合dst。 至less有一个轴(X或Y)将完全适合。 结果集中在dst中。

编辑:

这里的问题是, layout_height="wrap_content"不是“允许”图像展开。 你将不得不为它设置一个大小,以适应这个变化

  android:layout_height="wrap_content" 

  android:layout_height="100dp" // or whatever size you want it to be 

EDIT2:

工作正常:

 <ImageView android:id="@+id/imageView1" android:layout_width="match_parent" android:layout_height="300dp" android:scaleType="fitCenter" android:src="@drawable/img715945m" /> 

这是Mark Martinsson出色的解决scheme的一小部分。

如果图片的宽度大于高度,那么Mark的解决scheme会在屏幕的顶部和底部留出空间。

下面通过比较宽度和高度来解决这个问题:如果图像宽度> =高度,那么它将缩放高度以匹配屏幕高度,然后缩放宽度以保持宽高比。 同样,如果图像高度>宽度,则会缩放宽度以匹配屏幕宽度,然后缩放高度以保持宽高比。

换句话说,它正确地满足了scaleType="centerCrop"的定义:

http://developer.android.com/reference/android/widget/ImageView.ScaleType.html

均匀缩放图像(保持图像的高宽比),使图像的两个尺寸(宽度和高度) 等于或 大于视图的相应尺寸(减去填充)。

 package com.mypackage; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; public class FixedCenterCrop extends ImageView { public FixedCenterCrop(final Context context, final AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if(d != null) { int height = MeasureSpec.getSize(heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if(width >= height) height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); else width = (int) Math.ceil(height * (float) d.getIntrinsicWidth() / d.getIntrinsicHeight()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

此解决scheme自动在纵向或横向模式下工作。 就像你在Mark的解决scheme中一样,在你的布局中引用它。 例如:

 <com.mypackage.FixedCenterCrop android:id="@+id/imgLoginBackground" android:src="@drawable/mybackground" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:scaleType="centerCrop" /> 

我遇到了同样的问题,但具有固定的高度,缩放宽度保持图像的原始高宽比。 我通过加权的线性布局解决了这个问题。 您可以根据需要修改它。

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <ImageView android:id="@+id/image" android:layout_width="0px" android:layout_height="180dip" android:layout_weight="1.0" android:adjustViewBounds="true" android:scaleType="fitStart" /> </LinearLayout> 

Mark Matinsson的解决scheme还有一个补充。 我发现我的一些图像比其他图像缩放。 所以我修改了这个类,使图像按最大因子缩放。 如果图像太小,不能以最大宽度缩放而不模糊,则会停止缩放超出最大限制。

 public class DynamicImageView extends ImageView { final int MAX_SCALE_FACTOR = 2; public DynamicImageView(final Context context) { super(context); } @Override protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { final Drawable d = this.getDrawable(); if (d != null) { // ceil not round - avoid thin vertical gaps along the left/right edges int width = View.MeasureSpec.getSize(widthMeasureSpec); if (width > (d.getIntrinsicWidth()*MAX_SCALE_FACTOR)) width = d.getIntrinsicWidth()*MAX_SCALE_FACTOR; final int height = (int) Math.ceil(width * (float) d.getIntrinsicHeight() / d.getIntrinsicWidth()); this.setMeasuredDimension(width, height); } else { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } 

}