支持圆形裁剪框,裁剪后生成圆形图案。

代码基于开源项目修改,github上项目链接:https://github.com/shengge/android-crop

还是贴下效果图:

  

说一下圆形裁剪实现部分:

1.UI方面,自定义CircleHighlightView继承至HighlightView(原有的矩形裁剪框实现),直接看draw方法实现

**[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#) [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)
  <div>
    <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1">
    </embed>
  </div>
  
  

    <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> 
    
    
      - <span class="annotation">@Override</span>
      
      - <span class="keyword">protected</span> <span class="keyword">void</span> draw(Canvas canvas) {
      
      - canvas.save();
      
      - Path path = <span class="keyword">new</span> Path();
      
      - outlinePaint.setStrokeWidth( outlineWidth);
      
      - <span class="keyword">if</span>(!hasFocus()) {<span class="comment">//没焦点是,直接画一个黑色的矩形框</span>
      
      - outlinePaint.setColor( Color.BLACK);
      
      - canvas.drawRect( drawRect, outlinePaint);
      
      - }
      
      - <span class="keyword">else</span> {
      
      - Rect viewDrawingRect = <span class="keyword">new</span> Rect();
      
      - viewContext.getDrawingRect( viewDrawingRect);
      
      - 
      - <span class="comment">//已裁剪框drawRect,算出圆的半径</span>
      
      
      - <span class="comment">//添加一个圆形</span>
      
      - path.addCircle( drawRect.left + radius, drawRect.top + radius, radius, Direction.CW);
      
      - outlinePaint.setColor( highlightColor);
      
      - 
      - <span class="comment">//裁剪画布,path之外的区域,以outsidePaint填充</span>
      
      - canvas.clipPath( path, Region.Op.DIFFERENCE);
      
      - canvas.drawRect( viewDrawingRect, outsidePaint);
      
      - 
      - canvas.restore();
      
      - <span class="comment">//绘制圆上高亮线,这里outlinePaint定义的Paint.Style.STROKE:表示只绘制几何图形的轮廓。</span>
      
      - canvas.drawPath( path, outlinePaint);
      
      - 
      - <span class="comment">//当modifyMode为grow时,绘制handles,也就是那四个小圆</span>
      
      - <span class="keyword">if</span>(handleMode == HandleMode.Always || (handleMode == HandleMode.Changing && modifyMode == ModifyMode.Grow)) {
      
      - drawHandles( canvas);
      
      - }
      
      - }
      
      - }
      
    </div> 
    
    

      这里就实现了画圆形裁剪框的操作。
    

    
    ### <a name="t1"></a>2. 响应和处理用户触摸事件
    
    #### <a name="t2"></a>1). 判断触摸点坐标与圆的位置
    
    <div>
    </div>
    
    <div>
      <div class="dp-highlighter bg_java">
        <div class="bar">
          <div class="tools">
            **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)</span></span>

            
            <div>
              <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2">
              </embed>
            </div>
            
            

              <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> 
              
              
                - <span class="comment">/**</span>
                
                - <span class="comment">     * 根据x,y坐标,计算其与圆的关系(圆上、圆内、圆外)</span>
                
                - <span class="comment">     * @param x</span>
                
                - <span class="comment">     * @param y</span>
                
                - <span class="comment">     * @return</span>
                
                - <span class="comment">     */</span>
                
                - <span class="keyword">private</span> <span class="keyword">int</span> getHitOnCircle(<span class="keyword">float</span> x, <span class="keyword">float</span> y) {
                
                - Rect r = computeLayout();
                
                - <span class="keyword">int</span> retval = GROW_NONE;
                
                - <span class="keyword">final</span> <span class="keyword">float</span> hysteresis = 20F;
                
                
                - 
                - <span class="keyword">int</span> centerX = r.left + radius;
                
                - <span class="keyword">int</span> centerY = r.top + radius;
                
                - 
                - <span class="comment">//判断触摸位置是否在圆上</span>
                
                
                - <span class="keyword">double</span> rRadius = Math.sqrt( ret);
                
                
                - 
                - <span class="keyword">if</span>(gap <= hysteresis) {<span class="comment">// 圆上。这里由于是继承至HighlightView(绘制矩形框的)来处理,所以模拟返回了左右上下,而非纯圆上,亲测可用。你也可以自定义。</span>
                
                - <span class="keyword">if</span>(x < centerX) {<span class="comment">// left</span>
                
                - retval |= GROW_LEFT_EDGE;
                
                - }
                
                - <span class="keyword">else</span> {
                
                - retval |= GROW_RIGHT_EDGE;
                
                - }
                
                - 
                - <span class="keyword">if</span>(y < centerY) {<span class="comment">// up</span>
                
                - retval |= GROW_TOP_EDGE;
                
                - }
                
                - <span class="keyword">else</span> {
                
                - retval |= GROW_BOTTOM_EDGE;
                
                - }
                
                - }
                
                - <span class="keyword">else</span> <span class="keyword">if</span>(rRadius > radius) {<span class="comment">// outside</span>
                
                - retval = GROW_NONE;
                
                - }
                
                - <span class="keyword">else</span> <span class="keyword">if</span>(rRadius < radius) {<span class="comment">// inside,圆内就执行move</span>
                
                - retval = MOVE;
                
                - }
                
                - 
                - <span class="keyword">return</span> retval;
                
                - }
                
              </div> 
              
              

                由于是继承至HighLightView(矩形框)来实现的,如果点(x,y)位置圆上,还需判断其它那个象限,对应矩形的上下左右位置。
              <div>
              </div>
              
              #### <a name="t3"></a>2).  移动裁剪框
              
              <div>
                若上一步判断,触摸点在圆内,就会返回MOVE,并处理移动过程。
              </div>
              
              <div>
              </div>
              
              <div>
                <div class="dp-highlighter bg_java">
                  <div class="bar">
                    <div class="tools">
                      **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)</span></span>

                      
                      <div>
                        <embed id="ZeroClipboardMovie_3" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_3">
                        </embed>
                      </div>
                      
                      

                        <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> 
                        
                        
                          - <span class="comment">// Grows the cropping rectangle by (dx, dy) in image space</span>
                          
                          - <span class="keyword">void</span> moveBy(<span class="keyword">float</span> dx, <span class="keyword">float</span> dy) {
                          
                          - Rect invalRect = <span class="keyword">new</span> Rect(drawRect);
                          
                          - <span class="comment">//移动</span>
                          
                          - cropRect.offset(dx, dy);
                          
                          - 
                          - <span class="comment">// Put the cropping rectangle inside image rectangle</span>
                          
                          - cropRect.offset(
                          
                          
                          
                          - 
                          - cropRect.offset(
                          
                          
                          
                          - 
                          - drawRect = computeLayout();
                          
                          - invalRect.union(drawRect);
                          
                          - invalRect.inset(-(<span class="keyword">int</span>) handleRadius, -(<span class="keyword">int</span>) handleRadius);
                          
                          - viewContext.invalidate(invalRect);
                          
                          - }
                          
                        </div> 
                        
                        

                          移动裁剪框并保证其它image图片显示范围内。
                        <div>
                        </div>
                        
                        #### <a name="t4"></a>3). 缩放裁剪框
                        
                        <div>
                          此过程和上一步类似,将cropRect矩阵进行等比缩放即可,这里就细说了,详见代码:HighLightView.growBy(float dx, float dy)
                        </div>
                        
                        <div>
                        </div>
                        
                        ### <a name="t5"></a>3.将裁剪图片保存为圆形
                        
                        <div>
                          <div class="dp-highlighter bg_java">
                            <div class="bar">
                              <div class="tools">
                                **[java]** [view plain](http://blog.csdn.net/jiantao_yang/article/details/43635581#)<span class="tracking-ad" data-mod="popu_168"><span class="tracking-ad" data-mod="popu_168"> [copy](http://blog.csdn.net/jiantao_yang/article/details/43635581#)</span></span>

                                
                                <div>
                                  <embed id="ZeroClipboardMovie_4" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_4">
                                  </embed>
                                </div>
                                
                                

                                  <span class="tracking-ad" data-mod="popu_167">[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/600342)</span><span class="tracking-ad" data-mod="popu_170">[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/600342/fork)</span></div> </div> 
                                  
                                  
                                    - <span class="comment">/**</span>
                                    
                                    - <span class="comment">     * @param bitmap src图片</span>
                                    
                                    - <span class="comment">     * @return</span>
                                    
                                    - <span class="comment">     */</span>
                                    
                                    - <span class="keyword">public</span> <span class="keyword">static</span> Bitmap getCircleBitmap(Bitmap bitmap) {
                                    
                                    - Bitmap output = Bitmap.createBitmap( bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
                                    
                                    - Canvas canvas = <span class="keyword">new</span> Canvas( output);
                                    
                                    - 
                                    - <span class="keyword">final</span> <span class="keyword">int</span> color = <span class="number">0xff424242</span>;
                                    
                                    - <span class="keyword">final</span> Paint paint = <span class="keyword">new</span> Paint();
                                    
                                    - <span class="keyword">final</span> Rect rect = <span class="keyword">new</span> Rect( <span class="number"></span>, <span class="number"></span>, bitmap.getWidth(), bitmap.getHeight());
                                    
                                    - 
                                    - paint.setAntiAlias( <span class="keyword">true</span>);
                                    
                                    - paint.setFilterBitmap( <span class="keyword">true</span>);
                                    
                                    - paint.setDither( <span class="keyword">true</span>);
                                    
                                    - canvas.drawARGB( <span class="number"></span>, <span class="number"></span>, <span class="number"></span>, <span class="number"></span>);
                                    
                                    - paint.setColor( color);
                                    
                                    - <span class="comment">//在画布上绘制一个圆</span>
                                    
                                    - canvas.drawCircle( bitmap.getWidth() / <span class="number">2</span>, bitmap.getHeight() / <span class="number">2</span>, bitmap.getWidth() / <span class="number">2</span>, paint);
                                    
                                    - paint.setXfermode( <span class="keyword">new</span> PorterDuffXfermode( Mode.SRC_IN));
                                    
                                    - canvas.drawBitmap( bitmap, rect, rect, paint);
                                    
                                    - <span class="keyword">return</span> output;
                                    
                                    - }
                                    
                                  </div> 
                                  
                                  

                                    注意:将bitmap保存为file时,格式请选择png,不然会出现黑色背景。
                                  <div>
                                  </div>
                                  
                                  <div>
                                    鉴于水平有限,从小语文就没学好,描述比较凌乱,需要深入理解的请阅读[源代码](http://download.csdn.net/detail/jiantao_yang/8433015)。
                                  </div>
                                  
                                  <div>
                                  </div>
                                  
                                  <div>
                                    附:另外一个很好开源项目 https://github.com/edmodo/cropper
                                  </div>