背景
今天在討論UI優(yōu)化的時候,首頁有個控件支持動態(tài)切換背景圖,但是該控件的高度并不固定贺拣,如果直接使用圖片背景的話會照成圖片失真鸦难,如下圖(子控件顯示條數(shù)不固定)
這時候ui妹子突然說圖片由下往上展示,上面超出部分就不顯示了 iOS妹子和小程序小伙異口同聲說“沒問題”片林,但是又不能說Android搞不了端盆,只能笑著說沒問題(MMP),然后就開始研究起方案费封。
嘗試方案一(失敾烂睢)(scaleType)
第一個嘗試方案肯定是scaleType了,記得有個fitEnd的屬性平時用的少弓摘,然后發(fā)現(xiàn)并不符合預期焚鹊,全部效果如下
嘗試方案二(失敗)-自定義Glide的Transform
思路:自定義Transform韧献,等Glide下載完圖片的時候回調(diào)transform接口末患,通過修改Bitmap的RectF區(qū)域來進行顯示部分圖片,然后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;
}
但通過實際發(fā)現(xiàn)锤窑,設置成scaleType:fitXY 璧针,這樣實際操作還會存在圖片失真的情況,且裁剪的區(qū)域是已經(jīng)顯示在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;//實際的偏移量(往上移需要為負數(shù))
matrix.postTranslate(0, dy);//進行平移
canvas.setMatrix(matrix);//設置畫布矩陣
}
super.onDraw(canvas);
}
}
實際效果如下:
總結:
問題的難度不高曲稼,但可以鍛煉解決問題思路索绪,還是要多點動手才行,今天也是搬磚的一天 要元氣滿滿哦贫悄。