Android ImageView可缩小图像到宽度,灵活高度,而不会裁剪或变形
经常问,从来没有回答(至less不能以可重现的方式)。
我有一个图像视图与比视图小的图像。 我想缩放图像到屏幕的宽度,并调整ImageView的高度以反映图像的比例正确的高度。
<ImageView android:layout_width="fill_parent" android:layout_height="wrap_content" />
这导致图像以其原始尺寸居中(小于屏幕宽度),并在边上留有边缘。 不好。
所以我补充说
android:adjustViewBounds="true"
同样的效果,不好。 我补充说
android:scaleType="centerInside"
同样的效果,不好。 我改变了centerInside
以fitCenter
。 同样的效果,不好。 我把中心centerInside
了centerCrop
。
android:scaleType="centerCrop"
现在,最后,图像缩放到屏幕的宽度 – 但在顶部和底部裁剪 ! 所以我改变了centerCrop
来fitXY
。
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); } }
}