需求
recyclerview 展示商品需要显示大量的图片,图片只需要顶部的角是圆角,底部的角是直角
遇到的问题
早期的时候我写过一个实现圆角的图片方式,但是有问题。滑动图片列表发现滑动卡顿,是因为我将drawable 转为Bitmap ,耗时严重 这个方法耗时有1ms~ 47ms,根据图片大小决定,所以滑动就感觉卡卡的
private Bitmap drawable2Bitmap(Drawable drawable){
//获取 Drawable 的内部宽高,包含 padding
int width = drawable.getIntrinsicWidth();
int height = drawable.getIntrinsicHeight();
//创建一个w,h的bitmap
Bitmap bitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
//设置绘画区域
drawable.setBounds(0,0,width,height);
drawable.draw(canvas);
return bitmap;
}
注意
需要跟Glide搭配使用,要使用.asBitmap().placeholder().error().into(target);
优化后的代码
public class FilletImageViewV2 extends android.support.v7.widget.AppCompatImageView {
//最后确认的宽高
private RectF drawRectF;
private Paint mPaint;
private Matrix matrix;
private BitmapShader bitmapShader;
private boolean topLeftRightCorner,bottomLeftRightCorner;//定义上面与下面的是否为圆角
private int radius = 5;
public FilletImageViewV2(Context context) {
this(context,null);
}
public FilletImageViewV2(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public FilletImageViewV2(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
private void init(Context context, AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.FilletImageView);
topLeftRightCorner = typedArray.getBoolean(R.styleable.FilletImageView_topLeftRightCorner,false);
bottomLeftRightCorner = typedArray.getBoolean(R.styleable.FilletImageView_bottomLeftRightCorner,false);
radius = typedArray.getInt(R.styleable.FilletImageView_filletImageRadius,5);
typedArray.recycle();
mPaint = new Paint();
mPaint.setAntiAlias(true);
matrix = new Matrix();
radius = dip2px(radius);
}
public int getRadius() {
return radius;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
drawRectF = new RectF(0,0,w,h);
}
@Override
protected void onDraw(Canvas canvas) {
//创建一个和原图大小的图片
if (this.getDrawable() == null){
return;
}
Bitmap sourceBitMap = ((BitmapDrawable)this.getDrawable()).getBitmap();
if (sourceBitMap == null){
return;
}
//创建一个和原图大小的图片
long startTime = System.currentTimeMillis(); //起始时间
Bitmap sourceBitMap = ((BitmapDrawable)this.getDrawable()).getBitmap();
long endTime = System.currentTimeMillis(); //结束时间
long runTime = endTime - startTime;
Log.i("test", String.format("方法使用时间 %d ms", runTime));
//BitmapShader 为着色器
bitmapShader = new BitmapShader(sourceBitMap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
// float scaleMax = 1.0f,scaleX=1.0f,scaleY=1.0f;
float scaleMax = 1.0f;
// 如果图片的宽或者高与view的宽高不匹配,计算出需要缩放的比例;缩放后的图片的宽高,一定要大于我们view的宽高;所以我们这里取大值;
if (getWidth() != sourceBitMap.getWidth() || getHeight() !=sourceBitMap.getHeight()){
/* scaleX = (float) getWidth() / (float)sourceBitMap.getWidth();
scaleY = (float)getHeight() / (float)sourceBitMap.getHeight();*/
scaleMax = Math.max((float) getWidth() / (float)sourceBitMap.getWidth(),(float)getHeight() / (float)sourceBitMap.getHeight());
}
//对我们创建出来的bitmap进行缩放
matrix.setScale(scaleMax,scaleMax);
bitmapShader.setLocalMatrix(matrix);
mPaint.setShader(bitmapShader);
//纠正圆角
// int radius = (int) (getRadius() * scaleMax);
//画出我们需要的直角图形
canvas.drawRoundRect(drawRectF,radius,radius,mPaint);
if (topLeftRightCorner){
//左边底部
canvas.drawRect(0,canvas.getHeight() - radius ,radius,canvas.getHeight(),mPaint);
//右边底部
canvas.drawRect(canvas.getWidth() - radius, canvas.getHeight() - radius,canvas.getWidth(),canvas.getHeight(),mPaint);
}
if (bottomLeftRightCorner){
//左边顶部
canvas.drawRect(0,0,radius,radius,mPaint);
//右边顶部
canvas.drawRect(canvas.getWidth() - radius,0,canvas.getWidth(),radius,mPaint);
}
}
public int dip2px(float dipValue){
final float scale = Resources.getSystem().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
}