Android自定义圆角ImageView 支持网络图片

 先看下效果图

          


             我们再来看一张CSDN的圆角图片

             

             从布局可以看出csdn app 的头像也是圆角的Image,但可以看到,有明显的毛刺感,不知道是csdn 程序员的疏忽还是 我手机的问题,本人手机(小米note)。不知道其他的小伙伴显示效果也是这样。

             好回到主题。其实实现圆角Image的方式有很多,今天所讲的是我认为比较简单的一种。首先我们需要了解Xfermode属性,什么意思呢?看一张图你就明白了

             

                  这是Xfermode属性的几种模式和效果,简单说明一下

                   Src和Dst分别是一张矩形和原型图片,当我们设置不同的模式,显示的效果就如上图所示。关于Xfermode这里不过多阐述,免得把大家绕晕了,我们这里只需要关注其中的SrcIn模式,可以看到这个模式取的是两张图片的交集部分。这就好办了,我们通常拿到img图片都是矩形,我们可以利用canvas画一个圆,然后利用SrcIn属性,取img和圆的交集,那么圆角ImageView是不是就轻易实现了呢?

                   这里先理一下思路,1、自定义两个属性来设置圆角的弧度,以及当前是否画纯圆。2、设置Xfermode属性为SrcIn 。就这简单两步圆角ImageView就实现了,接下来直接上代码。

        

[java]  view plain  copy
  1. import wu.han.himan_library.R;  
  2. import android.content.Context;  
  3. import android.content.res.TypedArray;  
  4. import android.graphics.Bitmap;  
  5. import android.graphics.Bitmap.Config;  
  6. import android.graphics.BitmapFactory;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.Matrix;  
  9. import android.graphics.Paint;  
  10. import android.graphics.PorterDuff;  
  11. import android.graphics.PorterDuffXfermode;  
  12. import android.graphics.RectF;  
  13. import android.graphics.drawable.BitmapDrawable;  
  14. import android.graphics.drawable.Drawable;  
  15. import android.util.AttributeSet;  
  16. import android.widget.ImageView;  
  17.   
  18. /** 
  19.  *  
  20.  * @author Mr.Himan 
  21.  * @version 1.0<br> 
  22.  *          2015年12月16日 09:28:25<br> 
  23.  *          图片圆角实现 
  24.  *  
  25.  */  
  26. public class CustomImageView extends ImageView {  
  27.     private Paint paint;  
  28.     private Paint paintBorder;  
  29.     private Bitmap mSrcBitmap;  
  30.     /** 
  31.      * 圆角的弧度 
  32.      */  
  33.     private float mRadius;  
  34.     private boolean mIsCircle;  
  35.   
  36.     public CustomImageView(final Context context) {  
  37.         this(context, null);  
  38.     }  
  39.   
  40.     public CustomImageView(Context context, AttributeSet attrs) {  
  41.         this(context, attrs, R.attr.customImageViewStyle);  
  42.     }  
  43.   
  44.     public CustomImageView(Context context, AttributeSet attrs, int defStyle) {  
  45.         super(context, attrs, defStyle);  
  46.         TypedArray ta = context.obtainStyledAttributes(attrs,  
  47.                 R.styleable.CustomImageView, defStyle, 0);  
  48.         mRadius = ta.getDimension(R.styleable.CustomImageView_radius, 0);  
  49.         mIsCircle = ta.getBoolean(R.styleable.CustomImageView_circle, false);  
  50.         int srcResource = attrs.getAttributeResourceValue(  
  51.                 "http://schemas.android.com/apk/res/android""src"0);  
  52.         if (srcResource != 0)  
  53.             mSrcBitmap = BitmapFactory.decodeResource(getResources(),  
  54.                     srcResource);  
  55.         ta.recycle();  
  56.         paint = new Paint();  
  57.         paint.setAntiAlias(true);  
  58.         paintBorder = new Paint();  
  59.         paintBorder.setAntiAlias(true);  
  60.     }  
  61.   
  62.     @Override  
  63.     public void onDraw(Canvas canvas) {  
  64.         int width = canvas.getWidth() - getPaddingLeft() - getPaddingRight();  
  65.         int height = canvas.getHeight() - getPaddingTop() - getPaddingBottom();  
  66.         Bitmap image = drawableToBitmap(getDrawable());  
  67.         if (mIsCircle) {  
  68.             Bitmap reSizeImage = reSizeImageC(image, width, height);  
  69.             canvas.drawBitmap(createCircleImage(reSizeImage, width, height),  
  70.                     getPaddingLeft(), getPaddingTop(), null);  
  71.   
  72.         } else {  
  73.   
  74.             Bitmap reSizeImage = reSizeImage(image, width, height);  
  75.             canvas.drawBitmap(createRoundImage(reSizeImage, width, height),  
  76.                     getPaddingLeft(), getPaddingTop(), null);  
  77.         }  
  78.     }  
  79.   
  80.     /** 
  81.      * 画圆角 
  82.      *  
  83.      * @param source 
  84.      * @param width 
  85.      * @param height 
  86.      * @return 
  87.      */  
  88.     private Bitmap createRoundImage(Bitmap source, int width, int height) {  
  89.         Paint paint = new Paint();  
  90.         paint.setAntiAlias(true);  
  91.         Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);  
  92.         Canvas canvas = new Canvas(target);  
  93.         RectF rect = new RectF(00, width, height);  
  94.         canvas.drawRoundRect(rect, mRadius, mRadius, paint);  
  95.         // 核心代码取两个图片的交集部分  
  96.         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));  
  97.         canvas.drawBitmap(source, 00, paint);  
  98.         return target;  
  99.     }  
  100.   
  101.     /** 
  102.      * 画圆 
  103.      *  
  104.      * @param source 
  105.      * @param width 
  106.      * @param height 
  107.      * @return 
  108.      */  
  109.     private Bitmap createCircleImage(Bitmap source, int width, int height) {  
  110.   
  111.         Paint paint = new Paint();  
  112.         paint.setAntiAlias(true);  
  113.         Bitmap target = Bitmap.createBitmap(width, height, Config.ARGB_8888);  
  114.         Canvas canvas = new Canvas(target);  
  115.         canvas.drawCircle(width / 2, height / 2, Math.min(width, height) / 2,  
  116.                 paint);  
  117.         // 核心代码取两个图片的交集部分  
  118.         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));  
  119.         canvas.drawBitmap(source, (width - source.getWidth()) / 2,  
  120.                 (height - source.getHeight()) / 2, paint);  
  121.         return target;  
  122.   
  123.     }  
  124.   
  125.     @Override  
  126.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  127.         int width = MeasureSpec.getSize(widthMeasureSpec);  
  128.         int height = MeasureSpec.getSize(heightMeasureSpec);  
  129.         setMeasuredDimension(width, height);  
  130.     }  
  131.   
  132.     /** 
  133.      * drawable转bitmap 
  134.      *  
  135.      * @param drawable 
  136.      * @return 
  137.      */  
  138.     private Bitmap drawableToBitmap(Drawable drawable) {  
  139.         if (drawable == null) {  
  140.             if (mSrcBitmap != null) {  
  141.                 return mSrcBitmap;  
  142.             } else {  
  143.                 return null;  
  144.             }  
  145.         } else if (drawable instanceof BitmapDrawable) {  
  146.             return ((BitmapDrawable) drawable).getBitmap();  
  147.         }  
  148.         Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),  
  149.                 drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);  
  150.         Canvas canvas = new Canvas(bitmap);  
  151.         drawable.setBounds(00, canvas.getWidth(), canvas.getHeight());  
  152.         drawable.draw(canvas);  
  153.         return bitmap;  
  154.     }  
  155.   
  156.     /** 
  157.      * 重设Bitmap的宽高 
  158.      *  
  159.      * @param bitmap 
  160.      * @param newWidth 
  161.      * @param newHeight 
  162.      * @return 
  163.      */  
  164.     private Bitmap reSizeImage(Bitmap bitmap, int newWidth, int newHeight) {  
  165.         int width = bitmap.getWidth();  
  166.         int height = bitmap.getHeight();  
  167.         // 计算出缩放比  
  168.         float scaleWidth = ((float) newWidth) / width;  
  169.         float scaleHeight = ((float) newHeight) / height;  
  170.         // 矩阵缩放bitmap  
  171.         Matrix matrix = new Matrix();  
  172.   
  173.         matrix.postScale(scaleWidth, scaleHeight);  
  174.         return Bitmap.createBitmap(bitmap, 00, width, height, matrix, true);  
  175.     }  
  176.   
  177.     /** 
  178.      * 重设Bitmap的宽高 
  179.      *  
  180.      * @param bitmap 
  181.      * @param newWidth 
  182.      * @param newHeight 
  183.      * @return 
  184.      */  
  185.     private Bitmap reSizeImageC(Bitmap bitmap, int newWidth, int newHeight) {  
  186.         int width = bitmap.getWidth();  
  187.         int height = bitmap.getHeight();  
  188.         int x = (newWidth - width) / 2;  
  189.         int y = (newHeight - height) / 2;  
  190.         if (x > 0 && y > 0) {  
  191.             return Bitmap.createBitmap(bitmap, 00, width, height, nulltrue);  
  192.         }  
  193.   
  194.         float scale = 1;  
  195.   
  196.         if (width > height) {  
  197.             // 按照宽度进行等比缩放  
  198.             scale = ((float) newWidth) / width;  
  199.   
  200.         } else {  
  201.             // 按照高度进行等比缩放  
  202.             // 计算出缩放比  
  203.             scale = ((float) newHeight) / height;  
  204.         }  
  205.         Matrix matrix = new Matrix();  
  206.         matrix.postScale(scale, scale);  
  207.         return Bitmap.createBitmap(bitmap, 00, width, height, matrix, true);  
  208.     }  
  209. }  
attr.xml

[html]  view plain  copy
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.   
  4.     <declare-styleable name="Theme">  
  5.         <attr name="customImageViewStyle" format="reference" />  
  6.     </declare-styleable>  
  7.     <!-- 自定义圆角ImageView -->  
  8.     <declare-styleable name="CustomImageView">  
  9.         <attr name="circle" format="boolean" />  
  10.         <attr name="radius" format="dimension" />  
  11.     </declare-styleable>  
  12.   
  13. </resources>  

到这里圆角ImageView就实现了,代码比较简单,同样的我们可以根据Xfermode设置不痛的模式,来实现不同的效果。需要注意的是,在上面代码中我做了图片的压缩和缩放操作,当我们有时在加载网络图片的时候,图片宽高往往是不确定的,所以这里的压缩和缩放处理,需要大家根据自己的业务需求进行相应的改动

猜你喜欢

转载自blog.csdn.net/smart_ljh/article/details/51606108
今日推荐