背景
今天在讨论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);
}
}
实际效果如下:
最终效果
总结:
问题的难度不高,但可以锻炼解决问题思路,还是要多点动手才行,今天也是搬砖的一天 要元气满满哦。
网友评论