Android ImageCropper 矩形 圆形 裁剪框

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

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

还是贴下效果图:

  

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

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

@Override
    protected void draw(Canvas canvas) {
        canvas.save();
        Path path = new Path();
        outlinePaint.setStrokeWidth( outlineWidth);
        if(!hasFocus()) {//没焦点是,直接画一个黑色的矩形框
            outlinePaint.setColor( Color.BLACK);
            canvas.drawRect( drawRect, outlinePaint);
        }
        else {
            Rect viewDrawingRect = new Rect();
            viewContext.getDrawingRect( viewDrawingRect);

            //已裁剪框drawRect,算出圆的半径
            float radius = (drawRect.right - drawRect.left) / 2;
            //添加一个圆形
            path.addCircle( drawRect.left + radius, drawRect.top + radius, radius, Direction.CW);
            outlinePaint.setColor( highlightColor);

            //裁剪画布,path之外的区域,以outsidePaint填充
            canvas.clipPath( path, Region.Op.DIFFERENCE);
            canvas.drawRect( viewDrawingRect, outsidePaint);

            canvas.restore();
            //绘制圆上高亮线,这里outlinePaint定义的Paint.Style.STROKE:表示只绘制几何图形的轮廓。
            canvas.drawPath( path, outlinePaint);

            //当modifyMode为grow时,绘制handles,也就是那四个小圆
            if(handleMode == HandleMode.Always || (handleMode == HandleMode.Changing && modifyMode == ModifyMode.Grow)) {
                drawHandles( canvas);
            }
        }
    }

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

2. 响应和处理用户触摸事件

1). 判断触摸点坐标与圆的位置

/**
     * 根据x,y坐标,计算其与圆的关系(圆上、圆内、圆外)
     * @param x
     * @param y
     * @return
     */
    private int getHitOnCircle(float x, float y) {
        Rect r = computeLayout();
        int retval = GROW_NONE;
        final float hysteresis = 20F;
        int radius = (r.right - r.left) / 2;

        int centerX = r.left + radius;
        int centerY = r.top + radius;

        //判断触摸位置是否在圆上
        float ret = (x - centerX) * (x - centerX) + (y - centerY) * (y - centerY);
        double rRadius = Math.sqrt( ret);
        double gap = Math.abs( rRadius - radius);

        if(gap <= hysteresis) {// 圆上。这里由于是继承至HighlightView(绘制矩形框的)来处理,所以模拟返回了左右上下,而非纯圆上,亲测可用。你也可以自定义。
            if(x < centerX) {// left
                retval |= GROW_LEFT_EDGE;
            }
            else {
                retval |= GROW_RIGHT_EDGE;
            }

            if(y < centerY) {// up
                retval |= GROW_TOP_EDGE;
            }
            else {
                retval |= GROW_BOTTOM_EDGE;
            }
        }
        else if(rRadius > radius) {// outside
            retval = GROW_NONE;
        }
        else if(rRadius < radius) {// inside,圆内就执行move
            retval = MOVE;
        }

        return retval;
    }

由于是继承至HighLightView(矩形框)来实现的,如果点(x,y)位置圆上,还需判断其它那个象限,对应矩形的上下左右位置。

2).  移动裁剪框

若上一步判断,触摸点在圆内,就会返回MOVE,并处理移动过程。

// Grows the cropping rectangle by (dx, dy) in image space
    void moveBy(float dx, float dy) {
        Rect invalRect = new Rect(drawRect);
        //移动
        cropRect.offset(dx, dy);

        // Put the cropping rectangle inside image rectangle
        cropRect.offset(
                Math.max(0, imageRect.left - cropRect.left),
                Math.max(0, imageRect.top  - cropRect.top));

        cropRect.offset(
                Math.min(0, imageRect.right  - cropRect.right),
                Math.min(0, imageRect.bottom - cropRect.bottom));

        drawRect = computeLayout();
        invalRect.union(drawRect);
        invalRect.inset(-(int) handleRadius, -(int) handleRadius);
        viewContext.invalidate(invalRect);
    }

移动裁剪框并保证其它image图片显示范围内。

3). 缩放裁剪框

此过程和上一步类似,将cropRect矩阵进行等比缩放即可,这里就细说了,详见代码:HighLightView.growBy(float dx, float dy)

3.将裁剪图片保存为圆形

/**
     * @param bitmap src图片
     * @return
     */
    public static Bitmap getCircleBitmap(Bitmap bitmap) {
        Bitmap output = Bitmap.createBitmap( bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas( output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect( 0, 0, bitmap.getWidth(), bitmap.getHeight());

        paint.setAntiAlias( true);
        paint.setFilterBitmap( true);
        paint.setDither( true);
        canvas.drawARGB( 0, 0, 0, 0);
        paint.setColor( color);
        //在画布上绘制一个圆
        canvas.drawCircle( bitmap.getWidth() / 2, bitmap.getHeight() / 2, bitmap.getWidth() / 2, paint);
        paint.setXfermode( new PorterDuffXfermode( Mode.SRC_IN));
        canvas.drawBitmap( bitmap, rect, rect, paint);
        return output;
    }

注意:将bitmap保存为file时,格式请选择png,不然会出现黑色背景。

鉴于水平有限,从小语文就没学好,描述比较凌乱,需要深入理解的请阅读源代码

附:另外一个很好开源项目 https://github.com/edmodo/cropper

原文:http://blog.csdn.net/jiantao_yang/article/details/43635581#t0

时间: 2025-01-11 03:14:06

Android ImageCropper 矩形 圆形 裁剪框的相关文章

基于PhotoView的头像/圆形裁剪控件

常见的图片裁剪有两种,一种是图片固定,裁剪框移动放缩来确定裁剪区域,早期见的比较多,缺点在于不能直接预览裁剪后的效果:还有一种现在比较普遍了,就是裁剪框固定,直接拖动缩放图片,便于预览裁剪结果. 我做的这个控件属于后者.一般来说,做图片裁剪的思路无外乎是先监听手势,获取坐标,再对图片变形,最后确定裁剪区域的坐标对位图进行裁剪,最后保存图片到本地.我嘛还是个技术小白,一想到要监控手势这些就头疼,碰巧项目之前为了做查看大图而引入了大名鼎鼎的第三方图片查看控件--PhotoView.于是转念一想,能不

自定义各种裁剪框、扫描框

由于项目的需要,我们需要三种裁剪框,矩形裁剪框相信大家都不陌生,矩形的比较简单,思路:例如:正方形的裁剪框,我们只需要设置画笔的颜色为半透明的,然后绘制上下左右四个矩形即可组成一个正方形,那么圆形的怎么画呢?如果是同样的思路,那么我们就需要画两个不规则的图形,来组成圆,关键的地方就是那个半圆弧怎么画?我想到了用path,下面大家看一下效果: 正方形: 圆形: 带角标的矩形: 下面看实现代码: /** * 绘制裁剪框 * * @param canvas */ private void drawSh

【Android】自定义圆形ImageView(圆形头像 可指定大小)

最近在仿手Q的UI,这里面经常要用到的就是圆形头像,看到 在android中画圆形图片的几种办法 这篇文章,了解了制作这种头像的原理.不过里面提供的方法还有一个不足的地方就是不能根据实际需求改变图片的大小,也就是说提供的原图是大尺寸的,转换之后的图片也是大尺寸的,这显然不符合我们实际项目中的需求.于是我对里面介绍的第一种方法做了一番改进,使其能直接在XML中指定图片的大小. 大体步骤 将原图居中裁剪成正方形 根据指定的宽度对正方形进行缩放 裁剪成圆形 效果 代码实现 package com.de

Android自带图片裁剪

方法: private void cutPhoto(Uri uri) { Intent intent = new Intent("com.android.camera.action.CROP"); intent.setDataAndType(uri, "image/*"); intent.putExtra("crop", true); // 裁剪框的比例,1:1 intent.putExtra("aspectX", 1); i

Android自定义ImageView圆形头像

效果图: 代码如下: RoundImageView.java import cn.comnav.evaluationsystem.R; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import a

Android开发技巧——大图裁剪

本篇内容是接上篇<Android开发技巧--定制仿微信图片裁剪控件> 的,先简单介绍对上篇所封装的裁剪控件的使用,再详细说明如何使用它进行大图裁剪,包括对旋转图片的裁剪. 裁剪控件的简单使用 XML代码 使用如普通控件一样,首先在布局文件里包含该控件: <com.githang.clipimage.ClipImageView xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+i

android圆角矩形有背景颜色

android 圆角矩形,渐变颜色,自定义 首先,在drawable目录下写一个xml,名字随便起(只要符合规范),代码如下: <span style="color:#009900;"><span style="background-color: rgb(255, 255, 255);"><?xml version="1.0" encoding="utf-8"?> <shape xml

从零开始学android&lt;AutoCompleteTextView随笔提示文本框.十九.&gt;

随笔提示功能可以很好的帮助用户进行方便的信息输入,而在Android之中也提供了与之类似的功能,而这个功能的实现就需要依靠android.widget.AutoCompleteTextView类完成,此类的继承结构如下: java.lang.Object ? android.view.View ? android.widget.TextView ? android.widget.EditText ? android.widget.AutoCompleteTextView No. 方法 类型 描述

Android的弹出登陆框的实现

最近在做一个项目,要用到登陆框,几经波折,最后用的是直接将Activity的Theme属性设置成Dialog,然后达到了我想要的效果. 下面是我的实现经历: 1.首先,我是直接使用AlertDialog来实现,确定是,形状有点难看,而且获得Dialog里面的控件略显麻烦(因为我要做的登陆框有一定的布局),然后就给我就放弃了,可能因为我太水了,不能很好的使用它 2.然后我就使用PopupWindow来实现,界面是达到了我的要求,控件的获得通过Inflater就可以获得了相对较简单,但是有一个缺点就