博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于Android圆形图片的一种优化方案(可以显示网络图片)
阅读量:5361 次
发布时间:2019-06-15

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

在 App中,我们经常看到圆形头像图片,然后网上也有很多开源的控件。刚好这个项目用到了,也去找了一些开源的,发现并不完美,所以只好自己优化了,废话不多说,先上效果图:

下面是源码:本人能理解的地方都加上注释了,大牛勿喷。

 

[java]  
 
 
  1. package com.xyt.ygcf.widget;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Bitmap;  
  6. import android.graphics.Canvas;  
  7. import android.graphics.Color;  
  8. import android.graphics.Paint;  
  9. import android.graphics.PorterDuff;  
  10. import android.graphics.PorterDuffXfermode;  
  11. import android.graphics.RectF;  
  12. import android.graphics.Xfermode;  
  13. import android.graphics.drawable.Drawable;  
  14. import android.graphics.drawable.NinePatchDrawable;  
  15. import android.util.AttributeSet;  
  16. import android.widget.ImageView;  
  17.   
  18. import com.xyt.yangguangchufang.R;  
  19.   
  20. public class CircleImageView extends ImageView {  
  21.   
  22.     private static final Xfermode MASK_XFERMODE;  
  23.     private Bitmap mask;  
  24.     private Paint paint;  
  25.     private int mBorderWidth = 10;  
  26.     private int mBorderColor = Color.parseColor("#f2f2f2");  
  27.   
  28.     static {  
  29.         PorterDuff.Mode localMode = PorterDuff.Mode.DST_IN;  
  30.         MASK_XFERMODE = new PorterDuffXfermode(localMode);  
  31.     }  
  32.   
  33.     public CircleImageView(Context paramContext) {  
  34.         super(paramContext);  
  35.     }  
  36.   
  37.     public CircleImageView(Context paramContext, AttributeSet paramAttributeSet) {  
  38.         this(paramContext, paramAttributeSet, 0);  
  39.     }  
  40.   
  41.     public CircleImageView(Context paramContext, AttributeSet paramAttributeSet, int paramInt) {  
  42.         super(paramContext, paramAttributeSet, paramInt);  
  43.         TypedArray a = paramContext.obtainStyledAttributes(paramAttributeSet, R.styleable.CircularImage);  
  44.         mBorderColor = a.getColor(R.styleable.CircularImage_border_color, mBorderColor);  
  45.         final int defalut = (int) (2 * paramContext.getResources().getDisplayMetrics().density + 0.5f);  
  46.         mBorderWidth = a.getDimensionPixelOffset(R.styleable.CircularImage_border_width, defalut);  
  47.         a.recycle();  
  48.     }  
  49.   
  50.     private boolean useDefaultStyle = false;  
  51.   
  52.     public void setUseDefaultStyle(boolean useDefaultStyle) {  
  53.         this.useDefaultStyle = useDefaultStyle;  
  54.     }  
  55.   
  56.     @Override  
  57.     protected void onDraw(Canvas paramCanvas) {  
  58.         if (useDefaultStyle) {  
  59.             super.onDraw(paramCanvas);  
  60.             return;  
  61.         }  
  62.         final Drawable localDrawable = getDrawable();  
  63.         if (localDrawable == null)  
  64.             return;  
  65.         if (localDrawable instanceof NinePatchDrawable) {  
  66.             return;  
  67.         }  
  68.         if (this.paint == null) {  
  69.             final Paint localPaint = new Paint();  
  70.             localPaint.setFilterBitmap(false);  
  71.             localPaint.setAntiAlias(true);  
  72.             localPaint.setXfermode(MASK_XFERMODE);  
  73.             this.paint = localPaint;  
  74.         }  
  75.         final int width = getWidth();  
  76.         final int height = getHeight();  
  77.         /** 保存layer */  
  78.         int layer = paramCanvas.saveLayer(0.0F, 0.0F, width, height, null, 31);  
  79.         /** 设置drawable的大小 */  
  80.         localDrawable.setBounds(0, 0, width, height);  
  81.         /** 将drawable绑定到bitmap(this.mask)上面(drawable只能通过bitmap显示出来) */  
  82.         localDrawable.draw(paramCanvas);  
  83.         if ((this.mask == null) || (this.mask.isRecycled())) {  
  84.             this.mask = createOvalBitmap(width, height);  
  85.         }  
  86.         /** 将bitmap画到canvas上面 */  
  87.         paramCanvas.drawBitmap(this.mask, 0.0F, 0.0F, this.paint);  
  88.         /** 将画布复制到layer上 */  
  89.         paramCanvas.restoreToCount(layer);  
  90.         drawBorder(paramCanvas, width, height);  
  91.     }  
  92.   
  93.     /** 
  94.      * 绘制最外面的边框 
  95.      *  
  96.      * @param canvas 
  97.      * @param width 
  98.      * @param height 
  99.      */  
  100.     private void drawBorder(Canvas canvas, final int width, final int height) {  
  101.         if (mBorderWidth == 0) {  
  102.             return;  
  103.         }  
  104.         final Paint mBorderPaint = new Paint();  
  105.         mBorderPaint.setStyle(Paint.Style.STROKE);  
  106.         mBorderPaint.setAntiAlias(true);  
  107.         mBorderPaint.setColor(mBorderColor);  
  108.         mBorderPaint.setStrokeWidth(mBorderWidth);  
  109.         /** 
  110.          * 坐标x:view宽度的一般 坐标y:view高度的一般 半径r:因为是view的宽度-border的一半 
  111.          */  
  112.         canvas.drawCircle(width >> 1, height >> 1, (width - mBorderWidth) >> 1, mBorderPaint);  
  113.         canvas = null;  
  114.     }  
  115.   
  116.     /** 
  117.      * 获取一个bitmap,目的是用来承载drawable; 
  118.      * <p> 
  119.      * 将这个bitmap放在canvas上面承载,并在其上面画一个椭圆(其实也是一个圆,因为width=height)来固定显示区域 
  120.      *  
  121.      * @param width 
  122.      * @param height 
  123.      * @return 
  124.      */  
  125.     public Bitmap createOvalBitmap(final int width, final int height) {  
  126.         Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;  
  127.         Bitmap localBitmap = Bitmap.createBitmap(width, height, localConfig);  
  128.         Canvas localCanvas = new Canvas(localBitmap);  
  129.         Paint localPaint = new Paint();  
  130.         final int padding = mBorderWidth - 3;  
  131.         /** 
  132.          * 设置椭圆的大小(因为椭圆的最外边会和border的最外边重合的,如果图片最外边的颜色很深,有看出有棱边的效果,所以为了让体验更加好, 
  133.          * 让其缩进padding px) 
  134.          */  
  135.         RectF localRectF = new RectF(padding, padding, width - padding, height - padding);  
  136.         localCanvas.drawOval(localRectF, localPaint);  
  137.         return localBitmap;  
  138.     }  
  139. }  

 

 

 

xml布局:

 

[html]  
 
 
  1. <com.xyt.ygcf.widget.CircleImageView  
  2.         xmlns:myxmlns="http://schemas.android.com/apk/res/com.xyt.yangguangchufang"  
  3.         android:id="@+id/fragment_my_image_user"  
  4.         android:layout_width="110dp"  
  5.         android:layout_height="110dp"  
  6.         android:layout_marginBottom="10dp"  
  7.         android:contentDescription="@null"  
  8.         android:scaleType="centerCrop"  
  9.         myxmlns:border_width="@dimen/circle_width"  
  10.         myxmlns:border_color="@color/f2f2f2"  
  11.         android:src="@drawable/ic_my_avar_unlogin" />  

attr文件:

 

 

[html]  
 
 
  1. <declare-styleable name="CircularImage">  
  2.        <attr name="border_width" format="dimension" />  
  3.        <attr name="border_color" format="color" />  
  4.    </declare-styleable>  

抽空还要认真研究一下canvas,理解还不是太深刻。

转载于:https://www.cnblogs.com/Free-Thinker/p/5996437.html

你可能感兴趣的文章
迷宫问题
查看>>
【FZSZ2017暑假提高组Day9】猜数游戏(number)
查看>>
泛型子类_属性类型_重写方法类型
查看>>
练习10-1 使用递归函数计算1到n之和(10 分
查看>>
Oracle MySQL yaSSL 不明细节缓冲区溢出漏洞2
查看>>
Code Snippet
查看>>
zoj 1232 Adventure of Super Mario
查看>>
组合数学 UVa 11538 Chess Queen
查看>>
Redis常用命令
查看>>
[转载]电脑小绝技
查看>>
windos系统定时执行批处理文件(bat文件)
查看>>
thinkphp如何实现伪静态
查看>>
BZOJ 1925: [Sdoi2010]地精部落( dp )
查看>>
c++中的string常用函数用法总结!
查看>>
Week03-面向对象入门
查看>>
一个控制台程序,模拟机器人对话
查看>>
Vue 2.x + Webpack 3.x + Nodejs 多页面项目框架(上篇——纯前端多页面)
查看>>
我的PHP学习之路
查看>>
【题解】luogu p2340 奶牛会展
查看>>
对PostgreSQL的 SPI_prepare 的理解。
查看>>