博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android 通过修改图片像素实现CircleImageView
阅读量:6798 次
发布时间:2019-06-26

本文共 7821 字,大约阅读时间需要 26 分钟。

hot3.png

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;    }}

 

 

 

转载于:https://my.oschina.net/ososchina/blog/3036297

你可能感兴趣的文章
AS3.0中的反射
查看>>
lynn trigger
查看>>
读书笔记:C++中利用智能指针和值型类防止内存非法访问
查看>>
关于“分叉/联接方案”的一般做法
查看>>
c# 如何通过反射 获取\设置属性值、
查看>>
FIS源码解析之use
查看>>
[zz]cocos2d-x如何优化内存的应用
查看>>
分享:Apache OpenNLP 1.5.3 发布
查看>>
PCB_栅格大小设置
查看>>
在eclipse 的整个工程中查找字符串
查看>>
[转]Android中的Intent详细讲解
查看>>
电商也要懂的实体渠道实战知识zz
查看>>
命令行管理远程windows.(Remote Command Line On Windows)
查看>>
调用webservice使用URLConnection调用webservice
查看>>
父亲节例行吐槽
查看>>
c#动态创建ODBC数据源
查看>>
修改visual studio2010 的快捷键,使用ctrl+W 关闭当前文档
查看>>
ckeditor
查看>>
pwd显示链接文件的真实路径
查看>>
架构和框架的区别
查看>>