Android 调整ImageView的大小以适应纵横比

Android 调整ImageView的大小以适应纵横比,android,imageview,Android,Imageview,我需要调整ImageView的大小,使其适合屏幕,保持相同的纵横比。以下条件适用: 图像是固定宽度(屏幕宽度的大小) 图像是从Internet下载的,即大小只能稍后确定 每个图像的纵横比都会有所不同;有些是高的,有些是方的,有些是平的 ImageView的高度需要更改,根据图像的纵横比可以更改为更大或更小 多余的高度被裁剪,不能像默认情况下那样有很多空白 例如,在一个400像素宽的屏幕上,一个小的50x50图像可以将图像缩放到400x400像素。一张800x200的图像可以缩放到400x10

我需要调整ImageView的大小,使其适合屏幕,保持相同的纵横比。以下条件适用:

  • 图像是固定宽度(屏幕宽度的大小)
  • 图像是从Internet下载的,即大小只能稍后确定
  • 每个图像的纵横比都会有所不同;有些是高的,有些是方的,有些是平的
  • ImageView的高度需要更改,根据图像的纵横比可以更改为更大或更小
  • 多余的高度被裁剪,不能像默认情况下那样有很多空白
例如,在一个400像素宽的屏幕上,一个小的50x50图像可以将图像缩放到400x400像素。一张800x200的图像可以缩放到400x100


我已经研究了大多数其他线程,许多建议的解决方案,如简单地更改
adjustViewBounds
scaleType
只会缩小图像,而不会放大图像。

我在这篇文章中借助Bob Lee的回答创建了它:

ImageView mImageView; // This is the ImageView to change

// Use this in onWindowFocusChanged so that the ImageView is fully loaded, or the dimensions will end up 0.
public void onWindowFocusChanged(boolean hasFocus) 
{
    super.onWindowFocusChanged(hasFocus);

    // Abstracting out the process where you get the image from the internet
    Bitmap loadedImage = getImageFromInternet (url);

    // Gets the width you want it to be
    intendedWidth = mImageView.getWidth();

    // Gets the downloaded image dimensions
    int originalWidth = loadedImage.getWidth();
    int originalHeight = loadedImage.getHeight();

    // Calculates the new dimensions
    float scale = (float) intendedWidth / originalWidth;
    int newHeight = (int) Math.round(originalHeight * scale);

    // Resizes mImageView. Change "FrameLayout" to whatever layout mImageView is located in.
    mImageView.setLayoutParams(new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.WRAP_CONTENT,
            FrameLayout.LayoutParams.WRAP_CONTENT));
    mImageView.getLayoutParams().width = intendedWidth;
    mImageView.getLayoutParams().height = newHeight;
}
现在在XML中使用它:

<com.yourpackage.widgets.AspectRatioImageView android:layout_centerHorizontal="true"
    android:src="@drawable/yourdrawable" android:id="@+id/image"
    android:layout_alignParentTop="true" android:layout_height="wrap_content"
    android:layout_width="match_parent" android:adjustViewBounds="true" />
<com.yourpackage.widgets.AspectRatioImageView 
android:src="@drawable/yourdrawable"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>


玩得开心

我更喜欢阿加瓦尔的答案,但有一些修改,因为它是可以恢复的:

package com.yourpackage.widgets;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.ViewGroup;

public class AspectRatioImageView extends AppCompatImageView {

    public AspectRatioImageView(Context context) 
    {       
        super(context);
        this.setScaleType(ScaleType.FIT_XY);
    }

    public AspectRatioImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setScaleType(ScaleType.FIT_XY);
    }

    public AspectRatioImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setScaleType(ScaleType.FIT_XY);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 
    {
        Drawable d = getDrawable();

        if (d != null && d.getIntrinsicHeight() > 0)
        {
            int width = getLayoutParams().width;
            int height = getLayoutParams().height;

            // تو این حالت مبنای محاسبات رو بر اساس طول در نظر می گیرم
            if (height == ViewGroup.LayoutParams.WRAP_CONTENT || (width > 0 &&  width < 10000))
            {
                if (width <= 0);
                width = MeasureSpec.getSize(widthMeasureSpec);

                if (width > 0)
                    height = width * d.getIntrinsicHeight() / d.getIntrinsicWidth();

                // ارتفاع نباید از بیشینه ارتفاع بیشتر باشه
                if (height > getMaxHeight()) {
                    height = getMaxHeight();
                    width = height * d.getIntrinsicWidth() / d.getIntrinsicHeight();
                }

            }
            else if (width == ViewGroup.LayoutParams.WRAP_CONTENT  || (height > 0 &&  height < 10000))
            {
                // اگر مقداری برای ارتفاع مشخص نشده بود ارتفاع پدر رو در نظر می گیریم
                if (height <= 0)
                    height = MeasureSpec.getSize(heightMeasureSpec);

                // اگه ارتفاع مشخص بود که می تونیم طول رو بر اساسش حساب کنیم
                if (height > 0)
                    width = height * d.getIntrinsicWidth() / d.getIntrinsicHeight();

                // طول نباید از بیشینه طول بیشتر باشه
                if (width > getMaxWidth()) {
                    width = getMaxWidth();
                    height = width * d.getIntrinsicHeight() / d.getIntrinsicWidth();
                }
            }

            // اگه محاسبات موفقیت آمیز بود
            if (width > 0 && height > 0)
                setMeasuredDimension(width, height);
                // در غیر اینصورت همه چی رو می سپریم به خود ایمیج ویو
            else
                super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
        else
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }
}
package com.yourpackage.widgets;
导入android.content.Context;
导入android.graphics.drawable.drawable;
导入android.support.v7.widget.AppCompatImageView;
导入android.util.AttributeSet;
导入android.view.ViewGroup;
公共类AspectRatioImageView扩展了AppCompatImageView{
公共AspectRatioImageView(上下文)
{       
超级(上下文);
此.setScaleType(ScaleType.FIT_XY);
}
公共AspectRatioImageView(上下文、属性集属性){
超级(上下文,attrs);
此.setScaleType(ScaleType.FIT_XY);
}
公共AspectRatioImageView(上下文上下文、属性集属性、int-defStyle){
超级(上下文、属性、定义样式);
此.setScaleType(ScaleType.FIT_XY);
}
@凌驾
测量时的保护空隙(内部宽度测量等级、内部高度测量等级)
{
Drawable d=getDrawable();
如果(d!=null&&d.getIntrinsicHeight()>0)
{
int width=getLayoutParams().width;
int height=getLayoutParams().height;
// تو این حالت مبنای محاسبات رو بر اساس طول در نظر می گیرم
如果(高度==ViewGroup.LayoutParams.WRAP_内容| | |(宽度>0且宽度<10000))
{
如果(宽度0)
高度=宽度*d.getIntrinsicHeight()/d.getIntrinsicWidth();
// ارتفاع نباید از بیشینه ارتفاع بیشتر باشه
如果(高度>getMaxHeight()){
高度=getMaxHeight();
宽度=高度*d.getIntrinsicWidth()/d.getIntrinsicHeight();
}
}
else if(width==ViewGroup.LayoutParams.WRAP|u CONTENT | | |(高度>0&&height<10000))
{
// اگر مقداری برای ارتفاع مشخص نشده بود ارتفاع پدر رو در نظر می گیریم
如果(高度0)
宽度=高度*d.getIntrinsicWidth()/d.getIntrinsicHeight();
// طول نباید از بیشینه طول بیشتر باشه
如果(宽度>getMaxWidth()){
宽度=getMaxWidth();
高度=宽度*d.getIntrinsicHeight()/d.getIntrinsicWidth();
}
}
// اگه محاسبات موفقیت آمیز بود
如果(宽度>0和高度>0)
设置测量尺寸(宽度、高度);
// در غیر اینصورت همه چی رو می سپریم به خود ایمیج ویو
其他的
超级测量(宽度测量、高度测量);
}
其他的
超级测量(宽度测量、高度测量);
}
}
现在在XML中使用它:

<com.yourpackage.widgets.AspectRatioImageView android:layout_centerHorizontal="true"
    android:src="@drawable/yourdrawable" android:id="@+id/image"
    android:layout_alignParentTop="true" android:layout_height="wrap_content"
    android:layout_width="match_parent" android:adjustViewBounds="true" />
<com.yourpackage.widgets.AspectRatioImageView 
android:src="@drawable/yourdrawable"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>


+1,很好也很简单,只是我会保护它不受
getIntrinsicWidth
为0的影响(尝试除以它会崩溃)adjustViewBounds也应该在AspectRatioImageView中完成