1、前言

有时候,我们在应用中加载图片时并不知道图片确切的宽高数值,但是需要保持宽高比,比如我就遇到这样的设计:图片的宽度填满屏幕,宽高比例为16:9,高度根据这个比例自适应。这样加载出来的图片就形同一张卡片。由于不同手机的屏幕宽度不一样,所以图片宽高无法提前在布局中确定,但好在我们还是可以在代码中动态实现的,现在我们就来看看吧。

2、UI布局

为了便于比较,我在布局中放置了两个ImageView,它们除了id以外,其它的属性都一样。一个正常加载图片,两一个则保持16:9的宽高比。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.lindroid.scaleimageview.SecondActivity">

    <TextView
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="普通加载"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:scaleType="centerCrop"
        android:id="@+id/iv_normal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:layout_marginTop="10dp"
        android:gravity="center"
        android:text="宽高比为16:9"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android:scaleType="centerCrop"
        android:id="@+id/iv_scale"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

另外,为了保持图片拉伸之后不变形,我们在所有的ImageView中都加上android:scaleType="centerCrop"属性。

3、在代码中动态设置宽高

3.1 计算图片左右间距

首先,我们当然是要拿到图片的宽度。前面提到的图片在宽度上占满屏幕的说法其实不太严谨,因为为了美观,我们往往在左右会留出一些间距。这里我们将左右间距都设为15dp,两者之和即为30dp.

        int padding = 15;
        int spacePx = (int) (UIUtil.dp2px(this, padding) * 2);

这里用到的工具类UIUtil代码如下:

public class UIUtil {
    /**
     * 获取屏幕高度(px)
     */
    public static int getScreenHeight(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;
    }
    /**
     * 获取屏幕宽度(px)
     */
    public static int getScreenWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

    public static float dp2px(Context context, float dp) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
    }

    public static float px2dp(Context context, float px) {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, px, context.getResources().getDisplayMetrics());
    }
}

3.2 计算图片宽度

知道了图片距离屏幕左右的间距,图片的宽度自然就是屏幕宽度减去左右间距之和了:

int imageWidth = UIUtil.getScreenWidth(this) - spacePx;

3.3 计算图片高度

得到宽度,现在就可以去计算高度了,首先要算出宽高比:

float scale = 16f / 9f;

注意这里一定要使用浮点型,不然scale的值就是1!

然后根据宽高比去算出高度:

int imageHeight = (int) (imageWidth / scale);

3.4 设置ImageView父布局参数

我们的ImageView的父布局是LinearLayout,所以通过它来设置ImageView的位置:

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( imageWidth,imageHeight);
        //设置左右边距
        params.leftMargin = (int) UIUtil.dp2px(this, padding);
        params.rightMargin = (int) UIUtil.dp2px(this, padding);
        ivScale.setLayoutParams(params);

左右的边距除了在布局中动态设置外,大家也可以到xml文件中设置,效果是一样的。

3.5 加载图片资源

最后一步当然是加载图片资源了。我这里加载的是本地文件,如果需要加载网络图片,大家可以使用Glide或者Picasso等框架:

ivScale.setImageResource(R.mipmap.cat);

实现的效果图如下:

效果图

跟普通加载的图片比起来,效果还是可以的。

最后随便给一下Activity中的完整代码吧:

public class MainActivity extends Activity {

    private ImageView ivNormal;
    private ImageView ivScale;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ivNormal = findViewById(R.id.iv_normal);
        ivScale = findViewById(R.id.iv_scale);
        ivNormal.setImageResource(R.mipmap.cat);

        //计算图片左右间距之和
        int padding = 15;
        int spacePx = (int) (UIUtil.dp2px(this, padding) * 2);
        //计算图片宽度
        int imageWidth = UIUtil.getScreenWidth(this) - spacePx;
        //计算宽高比,注意数字后面要加上f表示浮点型数字
        float scale = 16f / 9f;
        //根据图片宽度和比例计算图片高度
        int imageHeight = (int) (imageWidth / scale);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( imageWidth,imageHeight);
        //设置左右边距
        params.leftMargin = (int) UIUtil.dp2px(this, padding);
        params.rightMargin = (int) UIUtil.dp2px(this, padding);

        ivScale.setLayoutParams(params);
        ivScale.setImageResource(R.mipmap.cat);
    }
}

lindroid
214 声望13 粉丝

Android中级魔法师