自适应高度的ImageView

App中经常会用到ImageView, 比如头像, 详情等. 很多时候ImageView的宽高是固定的, 很多时候只有一个边固定另一个边不确定. 一般来说我们都会使用图片加载框架将图片加载到ImageView上, 如果因为有一个边不确定而使用wrap_content的话, 图片就会显示不出来. AdaptiveImageView就是针对宽固定而高不固定的情况.

宽固定而高不固定的情况一般用于阅读, 展示类App, 如新闻图片, 商品展示图片等. AdaptiveImageView的使用方式与ImageView没有任何区别, 把其当作ImageView就行:

<com.corelibs.views.AdaptiveImageView
    android:id="@+id/iv_picture"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginBottom="@dimen/activity_horizontal_margin"
    android:layout_marginTop="@dimen/activity_horizontal_margin"/>
@Bind(R.id.iv_picture) AdaptiveImageView ivPicture;

Picasso.with(this).load(test.imageUrl).into(ivPicture);

效果:

AdaptiveImageView的关键代码:

   @Override
    public void setImageDrawable(final Drawable drawable) {
        super.setImageDrawable(drawable);
        if (drawable != null) {
            post(new Runnable() {
                @Override public void run() {
                    float mWidth = getWidth();
                    float pWidth = drawable.getBounds().width();
                    float pHeight = drawable.getBounds().height();
                    int mHeight = (int) ((mWidth / pWidth) * pHeight);

                    LayoutParams params = getLayoutParams();
                    params.height = mHeight;
                    params.width = (int) mWidth;
                    setLayoutParams(params);
                }
            });
        }
    }

研究发现, Picasso为ImageView设置图片最终会调用setImageDrawable. 因此我们可以在此方法内做一些操作去设置ImageView的高度. 首先, 如果drawable不为空, 则通过drawable.getBounds()去获取drawable边界的宽和高. 在根据ImageView的宽与drawable的宽的比例去计算高度, 最后通过LayoutParams设置ImageView的高度. 为什么要使用post(new Runnable())方法? 因为有时候直接去获取drawable宽高会为0, post一下可以保证宽和高都有值.

Last updated