13

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

  • 图像是固定宽度(屏幕宽度的大小)
  • 图片是从网上下载的,即大小只能以后确定
  • 每个图像的纵横比会有所不同;有的高,有的方,有的平
  • ImageView 的高度需要根据图像的纵横比改变,要么变大要么变小
  • 多余的高度被裁剪,默认情况下不能有很多空白空间。

例如,在 400 像素宽的屏幕上显示 50x50 的微小图像会将图像缩放到 400x400 像素。一个 800x200 的图像将缩放到 400x100。

我查看了大多数其他线程,以及许多提出的解决方案,例如简单地更改adjustViewBounds并且scaleType只会缩小图像,而不是放大图像。

4

3 回答 3

26

我在这篇博文中的 Bob Lee 的回答的帮助下创建了它:Android:如何在保持纵横比的同时将图像拉伸到屏幕宽度?

package com.yourpackage.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;

public class AspectRatioImageView extends ImageView {

    public AspectRatioImageView(Context context) {
        super(context);
    }

    public AspectRatioImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AspectRatioImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
        setMeasuredDimension(width, height);
    }
}

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

玩得开心!

于 2013-12-06T15:09:41.930 回答
11
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;
}
于 2012-10-08T05:53:25.800 回答
2

我更喜欢 Agarwal 的回答并进行了一些修改,因为它是可重复的:

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

现在在 XML 中使用它:

<com.yourpackage.widgets.AspectRatioImageView 
android:src="@drawable/yourdrawable"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
于 2017-01-26T09:36:19.193 回答