缩放图像以填充ImageView宽度并保持宽高比

我有一个GridViewGridView的数据是来自服务器的请求。

这是GridView的项目布局:

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/analysis_micon_bg" android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/half_activity_vertical_margin" android:paddingLeft="@dimen/half_activity_horizontal_margin" android:paddingRight="@dimen/half_activity_horizontal_margin" android:paddingTop="@dimen/half_activity_vertical_margin" > <ImageView android:id="@+id/ranking_prod_pic" android:layout_width="fill_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:contentDescription="@string/app_name" android:scaleType="centerCrop" /> <TextView android:id="@+id/ranking_rank_num" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/ranking_prod_num" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/ranking_prod_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> 

我从服务器请求数据,获取图像URL和加载图像Bitmap

 public static Bitmap loadBitmapFromInputStream(InputStream is) { return BitmapFactory.decodeStream(is); } public static Bitmap loadBitmapFromHttpUrl(String url) { try { return loadBitmapFromInputStream((InputStream) (new URL(url).getContent())); } catch (Exception e) { Log.e(TAG, e.getMessage()); return null; } } 

并且在适配器中有getView(int position, View convertView, ViewGroup parent)方法的代码

 Bitmap bitmap = BitmapUtil.loadBitmapFromHttpUrl(product.getHttpUrl()); prodImg.setImageBitmap(bitmap); 

图像大小是210*210 。 我在我的Nexus 4上运行我的应用程序。图像确实填充ImageView宽度,但ImageView高度不缩放。 ImageView不显示整个图像。

我如何解决这个问题?

不使用任何自定义类或库:

 <ImageView android:id="@id/img" android:layout_width="fill_parent" android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitCenter" /> 

scaleType="fitCenter" (省略时默认)

  • 将使其像家长所允许的那样宽,并且根据需要保持高宽比。

scaleType="centerInside"

  • 如果src的内在宽度小于父宽度
    将水平居中图像
  • 如果src的内在宽度大于父宽度
    将使其与父母允许的范围一样宽,并且保持纵横比。

不要紧,如果你使用android:srcImageView.setImage*方法,关键可能是adjustViewBounds

我喜欢arnefm的答案,但他犯了一个小错误(见评论),我将尝试纠正:

 import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.ImageView; /** * ImageView that keeps aspect ratio when scaled */ public class ScaleImageView extends ImageView { public ScaleImageView(Context context) { super(context); } public ScaleImageView(Context context, AttributeSet attrs) { super(context, attrs); } public ScaleImageView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { try { Drawable drawable = getDrawable(); if (drawable == null) { setMeasuredDimension(0, 0); } else { int measuredWidth = MeasureSpec.getSize(widthMeasureSpec); int measuredHeight = MeasureSpec.getSize(heightMeasureSpec); if (measuredHeight == 0 && measuredWidth == 0) { //Height and width set to wrap_content setMeasuredDimension(measuredWidth, measuredHeight); } else if (measuredHeight == 0) { //Height set to wrap_content int width = measuredWidth; int height = width * drawable.getIntrinsicHeight() / drawable.getIntrinsicWidth(); setMeasuredDimension(width, height); } else if (measuredWidth == 0){ //Width set to wrap_content int height = measuredHeight; int width = height * drawable.getIntrinsicWidth() / drawable.getIntrinsicHeight(); setMeasuredDimension(width, height); } else { //Width and height are explicitly set (either to match_parent or to exact value) setMeasuredDimension(measuredWidth, measuredHeight); } } } catch (Exception e) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } } } 

因此,如果(例如)放在ScrollView ImageView将正确缩放,并且不会有任何尺寸问题

我曾经有过类似的问题。 我通过制作自定义的ImageView来解决这个问题。

 public class CustomImageView extends ImageView 

然后重写imageview的onMeasure方法。 我做了这样的事我相信:

  @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { try { Drawable drawable = getDrawable(); if (drawable == null) { setMeasuredDimension(0, 0); } else { float imageSideRatio = (float)drawable.getIntrinsicWidth() / (float)drawable.getIntrinsicHeight(); float viewSideRatio = (float)MeasureSpec.getSize(widthMeasureSpec) / (float)MeasureSpec.getSize(heightMeasureSpec); if (imageSideRatio >= viewSideRatio) { // Image is wider than the display (ratio) int width = MeasureSpec.getSize(widthMeasureSpec); int height = (int)(width / imageSideRatio); setMeasuredDimension(width, height); } else { // Image is taller than the display (ratio) int height = MeasureSpec.getSize(heightMeasureSpec); int width = (int)(height * imageSideRatio); setMeasuredDimension(width, height); } } } catch (Exception e) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } 

这将拉伸图像以适应屏幕,同时保持纵横比。

使用android:scaleType="centerCrop"

我做了类似于上面的事情,然后把我的头靠在墙上几个小时,因为它在RelativeLayout不起作用。 我结束了以下代码:

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

然后为了防止RelativeLayout忽略测量的尺寸,我做了这个:

  <FrameLayout android:id="@+id/image_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/something"> <com.example.ScaledImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="150dp"/> </FrameLayout> 

如果您在ImageView中将背景设置为背景,则不适用,需要在src(android:src)中设置。

谢谢。

在ImageView中使用这些属性来保持宽高比:

 android:adjustViewBounds="true" android:scaleType="fitXY" 

你可以尝试通过手动加载图像来做你正在做的事情,但我强烈build议看看通用图像加载器 。

我最近把它整合到了我的项目中,我不得不说它太棒了。 是否所有担心asynchronous,resize,为您caching图像。 集成和设置非常简单。 在5分钟内,你可以得到它想做的。

示例代码:

 //ImageLoader config DisplayImageOptions displayimageOptions = new DisplayImageOptions.Builder().showStubImage(R.drawable.downloadplaceholder).cacheInMemory().cacheOnDisc().showImageOnFail(R.drawable.loading).build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()). defaultDisplayImageOptions(displayimageOptions).memoryCache(new WeakMemoryCache()).discCache(new UnlimitedDiscCache(cacheDir)).build(); if (ImageLoader.getInstance().isInited()) { ImageLoader.getInstance().destroy(); } ImageLoader.getInstance().init(config); imageLoadingListener = new ImageLoadingListener() { @Override public void onLoadingStarted(String s, View view) { } @Override public void onLoadingFailed(String s, View view, FailReason failReason) { ImageView imageView = (ImageView) view; imageView.setImageResource(R.drawable.android); Log.i("Failed to Load " + s, failReason.toString()); } @Override public void onLoadingComplete(String s, View view, Bitmap bitmap) { } @Override public void onLoadingCancelled(String s, View view) { } }; //Imageloader usage ImageView imageView = new ImageView(getApplicationContext()); if (orientation == 1) { imageView.setLayoutParams(new LinearLayout.LayoutParams(width / 6, width / 6)); } else { imageView.setLayoutParams(new LinearLayout.LayoutParams(height / 6, height / 6)); } imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); imageLoader.displayImage(SERVER_HOSTNAME + "demos" + demo.getPathRoot() + demo.getRootName() + ".png", imageView, imageLoadingListener); 

这可以延迟加载图像,使它们正确地适应在加载时显示占位符图像的imageView的大小,并且在加载失败并caching资源时显示默认图标。

– 我还应该补充说,这个当前的configuration保持图像的高宽比,因此适用于你原来的问题

试试这个:它解决了我的问题

  android:adjustViewBounds="true" android:scaleType="fitXY" 

使用易于使用的毕加索..

在你的适配器..

 @Override public void getView(int position, View convertView, ViewGroup parent) { ImageView view = (ImageView) convertView.findViewById(R.id.ranking_prod_pic); Picasso.with(context).load(url).into(view); //url is image url //you can resize image if you want /* Picasso.with(context) .load(url) .resize(50, 50) .centerCrop() .into(view) */ } 

http://square.github.io/picasso/ 在这里输入图像描述

只需使用UniversalImageLoader并设置

 DisplayImageOptions.Builder() .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) .build(); 

在ImageView上没有比例设置

哟不需要任何Java代码。 你只需要:

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

关键在于宽度和高度的匹配父项

要创build宽度等于屏幕宽度的图像,并根据宽高比按比例设置高度,请执行以下操作。

 Glide.with(context).load(url).asBitmap().into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { // creating the image that maintain aspect ratio with width of image is set to screenwidth. int width = imageView.getMeasuredWidth(); int diw = resource.getWidth(); if (diw > 0) { int height = 0; height = width * resource.getHeight() / diw; resource = Bitmap.createScaledBitmap(resource, width, height, false); } imageView.setImageBitmap(resource); } }); 

希望这可以帮助。

尝试用这个简单的线…在图像视图标记添加此行在您的xml代码中添加任何依赖项android:scaleType =“fitXY”