Android图片底部对齐(scaleType底部对齐)

2021-11-19  本文已影响0人  木易杨yang

背景

今天在讨论UI优化的时候,首页有个控件支持动态切换背景图,但是该控件的高度并不固定,如果直接使用图片背景的话会照成图片失真,如下图(子控件显示条数不固定)

在这里插入图片描述
这时候ui妹子突然说图片由下往上展示,上面超出部分就不显示了 iOS妹子和小程序小伙异口同声说“没问题”,但是又不能说Android搞不了,只能笑着说没问题(MMP),然后就开始研究起方案。

尝试方案一(失败)(scaleType)

第一个尝试方案肯定是scaleType了,记得有个fitEnd的属性平时用的少,然后发现并不符合预期,全部效果如下

在这里插入图片描述

尝试方案二(失败)-自定义Glide的Transform

思路:自定义Transform,等Glide下载完图片的时候回调transform接口,通过修改Bitmap的RectF区域来进行显示部分图片,然后scaleType用fitXY,代码如下

@Override
protected Bitmap transform(@NonNull BitmapPool pool, @NonNull Bitmap toTransform, int outWidth, int outHeight) {
    return Crop(pool, toTransform);
}

private Bitmap Crop(BitmapPool pool, Bitmap toTransform) {
    if (toTransform == null) {
        return null;
    }
    int bpWidth = toTransform.getWidth();
    int bpHeight = toTransform.getHeight();
    float bpRatio = (bpWidth * 1f) / bpHeight;
    Bitmap result = pool.get(toTransform.getWidth(), toTransform.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(result);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setShader(new BitmapShader(toTransform, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP));
    RectF rectF;
    if (targetRatio > bpRatio) {
        float top = (bpWidth * height * 1f / width);
        rectF = new RectF(0f, top, bpWidth, bpHeight);
    } else {
        rectF = new RectF(0f, 0f, bpWidth, bpHeight);
    }
    canvas.drawRect(rectF, paint);
    return result;
}

但通过实际发现,设置成scaleType:fitXY ,这样实际操作还会存在图片失真的情况,且裁剪的区域是已经显示在imageView上面的图片,还要考虑缩放等问题,到这里久放弃了。

尝试方案三(有效)-自定义View修改Matrix

思路:因为图片的宽度会比View的宽度宽或者窄,所以要考虑缩放,然后把缩放后的图片平移到控件底部,这时候想到的是修改Canvas的Matrix。


在这里插入图片描述

相关代码

xml(scaleType设置为matrix,不要问为什么,问就是比较好处理)
    <com.study.MatrixBottomImageView
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:background="@android:color/holo_red_dark"
        android:scaleType="matrix"
        android:src="@drawable/icon_dog_bg" />
java代码也比较简单
/**
 * 底部对齐控件
 */
public class MatrixBottomImageView extends androidx.appcompat.widget.AppCompatImageView {
    /**
     * 控件宽高
     */
    private int width, height;
    /**
     * 控件矩阵
     */
    private Matrix matrix;

    public MatrixBottomImageView(Context context) {
        this(context, null);
    }

    public MatrixBottomImageView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MatrixBottomImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (width != w || height != h) {//宽高改变时需刷新值
            width = w;
            height = h;
        }
    }

    private void init() {
        matrix = new Matrix();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        Drawable drawable = getDrawable();
        if (drawable != null) {
            int intrinsicWidth = drawable.getIntrinsicWidth();//获取图片宽度
            int intrinsicHeight = drawable.getIntrinsicHeight();//获取图片高度
            matrix.reset();
            float sx = width * 1f / intrinsicWidth;//求出缩放比例
            matrix.postScale(sx, sx, 0, 0);//以左上角为原点,进行缩放
            intrinsicHeight = (int) (intrinsicHeight * sx);//求出缩放后的图片高度
            int dy = -intrinsicHeight + height;//实际的偏移量(往上移需要为负数)
            matrix.postTranslate(0, dy);//进行平移
            canvas.setMatrix(matrix);//设置画布矩阵
        }
        super.onDraw(canvas);
    }
}

实际效果如下:


最终效果

总结:

问题的难度不高,但可以锻炼解决问题思路,还是要多点动手才行,今天也是搬砖的一天 要元气满满哦。

上一篇下一篇

猜你喜欢

热点阅读