Android 两种方式实现圆形头像

阳光穿透心脏的1/2处 2022-07-11 13:44 398阅读 0赞

方案一:继承自ImageView

  1. package com.chy.widget;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.graphics.PaintFlagsDrawFilter;
  7. import android.graphics.Path;
  8. import android.graphics.Region;
  9. import android.util.AttributeSet;
  10. import android.widget.ImageView;
  11. //有一个问题,当我把它放在列表项中, 然后列表上面有一个edittext用来filter, 结果发现该自定义imageview本该被edittext挡住, 结果却绘制在edittext之上
  12. //初步判断是由canvas.clipPath(path, Region.Op.REPLACE);引起的,它把第一次不存在的部分也画了
  13. //解决方案: REPLACE(覆盖) 改为 INTERSECT(交集)
  14. public class CircleImageView extends ImageView {
  15. private Paint paint = null;
  16. // 设置画布抗锯齿(毛边过滤)
  17. private PaintFlagsDrawFilter pfdf = null;
  18. private Path path = null;
  19. public CircleImageView(Context context) {
  20. super(context);
  21. init(context, null);
  22. }
  23. public CircleImageView(Context context, AttributeSet attrs) {
  24. super(context, attrs);
  25. init(context, attrs);
  26. }
  27. public CircleImageView(Context context, AttributeSet attrs, int defStyleAttr) {
  28. super(context, attrs, defStyleAttr);
  29. init(context, attrs);
  30. }
  31. // public CircleImageView(Context context, AttributeSet attrs, int
  32. // defStyleAttr, int defStyleRes) {
  33. // super(context, attrs, defStyleAttr, defStyleRes);
  34. // init(context, attrs);
  35. // }
  36. private void init(Context context, AttributeSet attrs) {
  37. paint = new Paint();
  38. // 透明度: 00%=FF(不透明) 100%=00(透明)
  39. paint.setColor(Color.WHITE);
  40. // paint.setColor(Color.parseColor("ffffffff"));
  41. paint.setStyle(Paint.Style.STROKE);
  42. // 解决图片拉伸后出现锯齿的两种办法: 1.画笔上设置抗锯齿 2.画布上设置抗锯齿
  43. // http://labs.easymobi.cn/?p=3819
  44. paint.setFlags(Paint.ANTI_ALIAS_FLAG);
  45. paint.setAntiAlias(true);
  46. int clearBits = 0;
  47. int setBits = Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG;
  48. pfdf = new PaintFlagsDrawFilter(clearBits, setBits);
  49. //由于imageview有默认底色,如黑色,设置背景为透明是为了第一次setImageBitmap时不显示圆以外方型的默认背景色
  50. //但是这样在中兴nubia手机上还会首先显示正方形黑色背景,然后才变圆(解决办法,先裁成圆再setImageBitmap)
  51. setBackgroundColor(context.getResources().getColor(android.R.color.transparent));
  52. }
  53. @Override
  54. protected void onDraw(Canvas canvas) {
  55. int width = getWidth();
  56. int height = getHeight();
  57. // CCW: CounterClockwise(逆时针)
  58. // CW: Clockwise(顺时针)
  59. if (path == null) {
  60. path = new Path();
  61. path.addCircle(width / 2f, height / 2f, Math.min(width / 2f, height / 2f), Path.Direction.CCW);
  62. path.close();
  63. }
  64. // canvas.drawCircle(width / 2f, height / 2f, Math.min(width / 2f, height / 2f), paint);
  65. // super.onDraw里面也可能有多个canvas.save
  66. int saveCount = canvas.save();
  67. canvas.setDrawFilter(pfdf);
  68. // Region.Op.REPLACE 是显示第二次的
  69. // canvas.clipPath(path, Region.Op.REPLACE);
  70. canvas.clipPath(path, Region.Op.INTERSECT);
  71. super.onDraw(canvas);
  72. canvas.restoreToCount(saveCount);
  73. }
  74. }

方案二:继承自View

  1. package com.chy.widget;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.BitmapFactory;
  5. import android.graphics.Canvas;
  6. import android.graphics.Color;
  7. import android.graphics.Matrix;
  8. import android.graphics.Paint;
  9. import android.graphics.PaintFlagsDrawFilter;
  10. import android.graphics.PorterDuff;
  11. import android.graphics.PorterDuffXfermode;
  12. import android.graphics.RectF;
  13. import android.util.AttributeSet;
  14. import android.view.View;
  15. import android.widget.ImageView.ScaleType;
  16. public class CircleView extends View {
  17. private Paint paint = null;
  18. private PaintFlagsDrawFilter pfdf = null;
  19. // 在已有的图像上绘图将会在其上面添加一层新的形状, 设置这两个形状的显示方式
  20. private PorterDuffXfermode xfermode = null;
  21. private RectF rectf = null;
  22. private Bitmap bitmap = null;
  23. private Bitmap destBmp = null;
  24. private Matrix matrix = null;
  25. private ScaleType scaleType = ScaleType.CENTER_CROP;
  26. public CircleView(Context context) {
  27. super(context);
  28. init(context, null);
  29. }
  30. public CircleView(Context context, AttributeSet attrs) {
  31. super(context, attrs);
  32. init(context, attrs);
  33. }
  34. public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
  35. super(context, attrs, defStyleAttr);
  36. init(context, attrs);
  37. }
  38. // public CircleView(Context context, AttributeSet attrs, int defStyleAttr,
  39. // int defStyleRes) {
  40. // super(context, attrs, defStyleAttr, defStyleRes);
  41. // init(context, attrs);
  42. // }
  43. private void init(Context context, AttributeSet attrs) {
  44. try {
  45. if (android.os.Build.VERSION.SDK_INT >= 11) {
  46. setLayerType(LAYER_TYPE_SOFTWARE, null);
  47. }
  48. } catch (Exception e) {
  49. e.printStackTrace();
  50. }
  51. paint = new Paint();
  52. paint.setStyle(Paint.Style.FILL);
  53. paint.setColor(Color.WHITE);
  54. // 透明度: 00%=FF(不透明) 100%=00(透明)
  55. // paint.setColor(Color.parseColor("#ffffffff"));
  56. // 解决图片拉伸后出现锯齿的两种办法: 1.画笔上设置抗锯齿 2.画布上设置抗锯齿
  57. paint.setFlags(Paint.ANTI_ALIAS_FLAG);
  58. paint.setAntiAlias(true);
  59. int clearBits = 0;
  60. int setBits = Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG;
  61. pfdf = new PaintFlagsDrawFilter(clearBits, setBits);
  62. // PorterDuff.Mode.MULTIPLY只显示重叠部分
  63. xfermode = new PorterDuffXfermode(PorterDuff.Mode.MULTIPLY);
  64. matrix = new Matrix();
  65. }
  66. public void setImageResource(int resId) {
  67. Bitmap bmp = BitmapFactory.decodeResource(getResources(), resId);
  68. setBitmap(bmp);
  69. }
  70. public void setBitmap(Bitmap bmp) {
  71. this.bitmap = bmp;
  72. }
  73. public void setScaleType(ScaleType scaleType) {
  74. this.scaleType = scaleType;
  75. }
  76. private void makeDestBmp(int width, int height) {
  77. destBmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
  78. rectf = new RectF(0, 0, width, height);
  79. Canvas canvas = new Canvas(destBmp);
  80. canvas.drawOval(rectf, paint);
  81. }
  82. @Override
  83. protected void onDraw(Canvas canvas) {
  84. if (bitmap == null) {
  85. return;
  86. }
  87. int width = getWidth();
  88. int height = getHeight();
  89. int bmpWidth = bitmap.getWidth();
  90. int bmpHeight = bitmap.getHeight();
  91. if (destBmp == null) {
  92. makeDestBmp(width, height);
  93. }
  94. // canvas.save();
  95. // 设置画布抗锯齿
  96. canvas.setDrawFilter(pfdf);
  97. canvas.drawBitmap(destBmp, 0, 0, paint);
  98. paint.setXfermode(xfermode);
  99. switch(scaleType) {
  100. case FIT_XY:
  101. canvas.drawBitmap(bitmap, null, rectf, paint);
  102. break;
  103. case CENTER_CROP:
  104. default:
  105. matrix.reset();
  106. float scale = Math.max((float) width / (float) bmpWidth, (float) height / (float) bmpHeight);
  107. // 默认绕原点进行缩放 matrix.postScale(scale, scale, 0, 0);
  108. matrix.postScale(scale, scale, 0, 0);
  109. matrix.postTranslate((width - bmpWidth * scale) / 2f, (height - bmpHeight * scale) / 2f);
  110. canvas.drawBitmap(bitmap, matrix, paint);
  111. break;
  112. }
  113. paint.setXfermode(null);
  114. // canvas.restore();
  115. }
  116. }

发表评论

表情:
评论列表 (有 0 条评论,398人围观)

还没有评论,来说两句吧...

相关阅读

    相关 圆形头像处理

    很多上传头像是会用到圆形的头像,今天写了一个小方法,可以把图片处理成圆形的,感觉有用的直接拿去用: 不多说直接上代码,希望大家多多支持 //把图片处理成圆形

    相关 Android圆形头像实现

    ![这里写图片描述][SouthEast] 如图所示,实现一个QQ圆形头像,话不多说,直接上代码,继承ImageView类,重写里面的方法: package com