android 实现部分圆角图片

2019-08-03  本文已影响0人  一个冬季
需求

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);
    }
}
    <declare-styleable name="FilletImageView">
        <attr name="filletImageRadius" format="integer"/>
        <attr name="topLeftRightCorner" format="boolean"/>
        <attr name="bottomLeftRightCorner" format="boolean"/>
    </declare-styleable>
上一篇 下一篇

猜你喜欢

热点阅读