网站/小程序/APP个性化定制开发,二开,改版等服务,加扣:8582-36016

    CircleImageView实现方法有很多种,各有优缺点,因此需要按照不同的场景使用。我们今天使用修改图片像素的方法实现CircleImageView,主要知识点无非是勾股定理和点到圆形的距离。

    素材图片:

     

    效果如下:

     

    1、clipPath裁剪画布

    该方法支持的最小版本是Android 4.3(API Level 18),方便快捷,但是不支持硬件加,此外也存在Path既有的缺点,不支持抗锯齿。

     @Override
        protected void onDraw(Canvas canvas) {        super.onDraw(canvas);
    
            Paint paint = new Paint();
    
            mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic);
            mPath = new Path();
    
            mPath.addCircle(mBitmap.getWidth() / 2, mBitmap.getHeight() / 2, mBitmap.getWidth() / 2, Path.Direction.CCW);
            canvas.clipPath(mPath);
            canvas.drawBitmap(mBitmap, 0, 0, paint);
        }

     

    2、使用PorterDuffXfermode

    PorterDuffXfermode是Android主流的图片合成工具,支持模式多,稳定性强,效果好,质量高,支持抗锯齿备受广大开发者喜爱,可以说是很多应用开发的首选。缺点是难度学习有些高,另外比较占内存。

     /**
         * 绘制圆形图片
         *
         */
        @Override  
        protected void onDraw(Canvas canvas) {  
      
            Drawable drawable = getDrawable();  
            if (null != drawable) {  
                Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();  
                Bitmap b = getCircleBitmap(bitmap);  
                final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());  
                final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
                paint.reset();  
                canvas.drawBitmap(b, rectSrc, rectDest, paint);  
      
            } else {  
                super.onDraw(canvas);  
            }  
        }  
      
        /**
         * 获取圆形图片方法
         * @param bitmap
         * @param pixels
         * @return Bitmap
         */
        private Bitmap getCircleBitmap(Bitmap bitmap) {  
            Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),  
                    bitmap.getHeight(), Config.ARGB_8888);  
            Canvas canvas = new Canvas(output);  
              
            final int color = 0xff424242;       
            final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());  
            paint.setAntiAlias(true);  
            canvas.drawColor(Color.TRANSPARENT);  
            paint.setColor(color);  
            int x = bitmap.getWidth(); 
            
            canvas.drawCircle(x / 2, x / 2, x / 2, paint);  
            paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));  
            canvas.drawBitmap(bitmap, rect, rect, paint);  
            return output;  
            
            
        }

    4、设置画笔Paint的Shader,然后用该画笔绘制圆形图片

    该方法是Glide和picasso使用的方法,用法简单便捷,占内占有率处于中等水平。

     
       
        @Override  
        protected void onDraw(Canvas canvas) {  
      
            Drawable drawable = getDrawable();  
            if (null != drawable) {  
                Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();  
                Bitmap b = transform(bitmap);  
                final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());  
                final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
                paint.reset();  
                canvas.drawBitmap(b, rectSrc, rectDest, paint);  
      
            } else {  
                super.onDraw(canvas);  
            }  
        } 
    
    public Bitmap transform(Bitmap source) {            int size = Math.min(source.getWidth(), source.getHeight());            int x = (source.getWidth() - size) / 2;            int y = (source.getHeight() - size) / 2;
    
                Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size);            if (squaredBitmap != source) {
                    source.recycle();
                }
    
                Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig());
    
                Canvas canvas = new Canvas(bitmap);
                Paint paint = new Paint();
                BitmapShader shader = new BitmapShader(squaredBitmap,
                        BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP);          float mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
    
              Matrix matrix = new Matrix();
              matrix.setScale(mScale, mScale);
              bitmapShader.setLocalMatrix(matrix);
    
    
                paint.setShader(shader);
                paint.setAntiAlias(true);            float r = size / 2f;
                canvas.drawCircle(r, r, r, paint);
    
                squaredBitmap.recycle();            return bitmap;
            }

    5、修改像素

    该方法无法支持抗锯齿,并且不支持Bitmap.Config.HARDWARE格式的bitmap,但用法简单,内存占有率同样处于比较低。

    public class CircleImageView extends AppCompatImageView {    public CircleImageView(Context context) {        this(context,null);
        }    public CircleImageView(Context context, AttributeSet attrs) {        this(context, attrs,0);
        }    public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);
        }    @Override
        public void onDraw(Canvas canvas) {        int width  = getWidth();        int height = getHeight();        int minSize = Math.min(width,height)/2;
            Drawable drawable = getDrawable();        if(drawable!=null && minSize!=0) {            if(Math.min(drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight())==0) {                return;
                }            int intrinsicWidth = drawable.getIntrinsicWidth();            int intrinsicHeight = drawable.getIntrinsicHeight();            float R = Math.min(intrinsicWidth, intrinsicHeight) / 2;
    
                Bitmap bmp = transformBitmap(drawable, intrinsicWidth, intrinsicHeight, R);
    
                Matrix imageMatrix = getImageMatrix();            if((imageMatrix==null || imageMatrix.isIdentity()) && getPaddingTop()==0 && getPaddingLeft()==0){
                    drawCircleImage(canvas, bmp);
    
                }else {                if (imageMatrix != null && !imageMatrix.isIdentity()) {
                        canvas.concat(imageMatrix);
                    }                final int saveCount = canvas.getSaveCount();
                    canvas.save();                if (getCropToPadding()) {                    final int scrollX = getScrollX();                    final int scrollY = getScrollY();
                        canvas.clipRect(scrollX + getPaddingLeft(), scrollY + getPaddingTop(),
                                scrollX + getRight() - getLeft() - getPaddingRight(),
                                scrollY + getBottom() - getTop() - getPaddingBottom());
                    }
    
                    canvas.translate(getPaddingLeft(), getPaddingTop());
                    drawCircleImage(canvas, bmp);
                    canvas.restoreToCount(saveCount);
    
                }            if(bmp!=null && !bmp.isRecycled()) {
                    bmp.recycle();
                }
            }else{            super.onDraw(canvas);
            }
        }    private void drawCircleImage(Canvas canvas, Bitmap bmp) {        try {
                DrawFilter drawFilter = canvas.getDrawFilter();
                canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG));
                canvas.drawBitmap(bmp, 0, 0, null);
                canvas.setDrawFilter(drawFilter);
            }catch (Exception e){
                e.printStackTrace();            return;
            }
        }    @NonNull
        private Bitmap transformBitmap(Drawable drawable, int intrinsicWidth, int intrinsicHeight, float r) {
            Bitmap bmp = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888);
            Canvas targetCanvas = new Canvas(bmp);        try {
                drawable.draw(targetCanvas);            for (int y = 0; y < intrinsicHeight; y++) {                for (int x = 0; x < intrinsicWidth; x++) {                    if ((Math.pow(x - intrinsicWidth / 2, 2) + Math.pow(y - intrinsicHeight / 2, 2)) <= Math.pow(r, 2)) {                        continue;
                        }
                        bmp.setPixel(x, y, Color.TRANSPARENT);
                    }
                }
            }catch (Exception e){
                NCFLog.e("transformBitmap","e="+e.getLocalizedMessage());
                e.printStackTrace();
            }        return bmp;
        }    public boolean isHardware(Bitmap sourceBitmap){        if(sourceBitmap==null) return  false;        if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.O) {            return sourceBitmap.getConfig() == Bitmap.Config.HARDWARE;
            }        return false;
        }
    
    }

    评论 0

    暂无评论
    0
    0
    0
    立即
    投稿
    发表
    评论
    返回
    顶部