首页 > 技术文章 > android 圆角 ImageView

checkway 2016-01-15 15:20 原文

android中Imageview 内的图片圆角的实现方式

此文针对的是 imageview中图片的圆角, 即忽略掉图片的ScaleType, 均对图片采取圆角.  而不是对Imageview本身的圆角.

 

处理方式分两大类(暂不讨论具体的实现方式)

  1. 传入图片前将图片圆角化.
  2. 传入图片之后在绘制过程中进行圆角化处理.

两种实现方式各有优劣.

  第一种实现方式在于每次调用之前需要对原图进行圆角化处理, 图片处理一般是比较耗时的操作(大图片比较明显), 而且处理完成后原图就本身带圆角, 不利于获取原来的图片, 此方法同时也是优势.....(无视那些保存原图的小伙伴.....)   

  第二种方式. 优势在于不需要对图片额外处理, 只需要执行正常的调用逻辑,  是在图片绘制中进行额外处理, 所以时间耗费比方法一少. 不过此种方法处理过的图形本身不带圆角, 只是显示中才有圆角. 而且此种方法实现过程中难点在于获取图片在imageview中的显示位置.

 

方法二:  

  步骤一, 对图片的绘制过程进行控制, 需要计算出 imageview 中的图片的显示位置, 然后根据位置进行圆角绘制.

  根据imageview中图片的scaletype 不一样, 动态的计算图像在imageview中的位置.  核心代码如下

  

 1     private RectF genBounds() {
 2         RectF ret = new RectF(0, 0, 0, 0);
 3 
 4         if (getDrawable() == null) {
 5             return ret;
 6         }
 7 
 8         int dwidth = getDrawable().getIntrinsicWidth();
 9         int dheight = getDrawable().getIntrinsicHeight();
10 
11         int vwidth = getWidth() - getPaddingLeft() - getPaddingRight();
12         int vheight = getHeight() - getPaddingTop() - getPaddingBottom();
13 
14         boolean fits = (dwidth < 0 || vwidth == dwidth) &&
15                 (dheight < 0 || vheight == dheight);
16 
17         if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == getScaleType()) {
18             ret.right = vwidth;
19             ret.bottom = vheight;
20         } else {
21             ret = new RectF(0, 0, dwidth, dheight);
22 
23             if (ScaleType.MATRIX == getScaleType()) {
24                 // Use the specified matrix as-is.
25             } else if (fits) {
26             } else if (ScaleType.CENTER == getScaleType()) {
27                 ret.offset((int) ((vwidth - dwidth) * 0.5f + 0.5f),
28                         (int) ((vheight - dheight) * 0.5f + 0.5f));
29             } else if (ScaleType.CENTER_CROP == getScaleType()) {
30 
31                 float scale;
32                 float dx = 0, dy = 0;
33 
34                 if (dwidth * vheight > vwidth * dheight) {
35                     scale = (float) vheight / (float) dheight;
36                     dx = (vwidth - dwidth * scale) * 0.5f;
37                 } else {
38                     scale = (float) vwidth / (float) dwidth;
39                     dy = (vheight - dheight * scale) * 0.5f;
40                 }
41 
42                 ret.offset((int) (dx + 0.5f), (int) (dy + 0.5f));
43             } else if (ScaleType.CENTER_INSIDE == getScaleType()) {
44                 float scale;
45                 int dx;
46                 int dy;
47 
48                 if (dwidth <= vwidth && dheight <= vheight) {
49                     scale = 1.0f;
50                 } else {
51                     scale = Math.min((float) vwidth / (float) dwidth,
52                             (float) vheight / (float) dheight);
53                 }
54 
55                 dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
56                 dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
57 
58                 ret.offset(dx, dy);
59             }
60         }
61 
62         if (ret.left < getPaddingLeft())
63             ret.left = getPaddingLeft();
64 
65         if (ret.right > vwidth + getPaddingLeft())
66             ret.right = vwidth + getPaddingLeft();
67 
68         if (ret.top < getPaddingTop()) ret.top = getPaddingTop();
69 
70         if (ret.bottom > vheight + getPaddingTop())
71             ret.bottom = vheight + getPaddingTop();
72 
73         return ret;
74     }

  步骤二: 对图片的绘制进行处理.

  

 1     private int cornerColor = Color.WHITE;
 2     private boolean usrRoundCorner = true;
 3     private Path mMaskPath = new Path();
 4 
 5     private void initPaint() {
 6         if (mPaint == null) {
 7             mPaint = new Paint();
 8             mPaint.setColor(getCornerColor());
 9             mPaint.setStrokeWidth(3);
10             mPaint.setAntiAlias(true);
11             mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
12         }
13     }
14 
15     Paint mPaint;
16     float mCornerRadius = getResources().getDisplayMetrics().density * 3 + 0.5f;
17     float[] radii = new float[]{mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius};
18 
19     @Override
20     protected void onDraw(Canvas canvas) {
21         int saveCount = canvas.saveLayerAlpha(0F, 0F, canvas.getWidth(), canvas.getHeight(), 255, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG);
22         super.onDraw(canvas);
23 
24         if (usrRoundCorner) {
25             RectF bounds = genBounds();
26 
27             mMaskPath.reset();
28             mMaskPath.addRoundRect(bounds, radii, Path.Direction.CW);
29             mMaskPath.setFillType(Path.FillType.INVERSE_WINDING);
30 
31             canvas.drawPath(mMaskPath, mPaint);
32         }
33         canvas.restoreToCount(saveCount);
34     }

 

核心代码都在上面了.  大家有其他方法也可以留言告诉我.

 

推荐阅读