Android 自定义view 图片编辑(画圆,画长方形,手势缩放)

Android 自定义view 图片编辑(画圆,画长方形,手势缩放)

package com.bridgetek.yqm.view;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.widget.ImageView;

import com.bridgetek.yqm.R;

import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@SuppressLint(“AppCompatCustomView”)
public class GraffitiView extends ImageView {
private List list = new ArrayList<>(); //保存每次修改后图片,回撤使用
private Paint paint; //画笔
private Bitmap originalBitmap; //源图
private Bitmap newBitmap;
private Bitmap finalBitmap; //最终保存时的图片
private Bitmap finalOvalBitmap;
private Bitmap finalRectBitmap;
private Bitmap finalArrowBitmap;
private Bitmap finalTextBitmap;

private float clickX = 0;  //触摸时的x坐标
private float clickY = 0;  //触摸时的y坐标
private float startX = 0;  //每次绘制起点的x坐标
private float startY = 0;  //每次绘制起点的y坐标

private boolean isEdit = false;  //是否允许对图片进行编辑
private boolean isMove = true;  //是否进行绘制
private boolean isClear = false;  //是否进行清空
private int drawType = 2;  //绘制类型:0---线条;1---圆;2---矩形;3---箭头;4---文字
private String text;

private int color = Color.RED;  //画笔颜色
private float strokeWidth = 4.0f;  //涂鸦线条的宽度
private int textSize = 18;  //字体大小
private int textColor = getResources().getColor(R.color.colorPrimary);  //文字颜色

private int mScreenWidth;
private int mScreenHeight;

private String filePath;

//原始图像矩阵
private Matrix mMatrix=new Matrix();
//过程图像矩阵
private Matrix mSavedMatrix=new Matrix();
//结果图像矩阵
private Matrix mResultMatrix=new Matrix();
//定义三种模式:None、Drag、Zoom
public static final int Mode_None=0;
public static final int Mode_Drag=1;
public static final int Mode_Zoom=2;
//当前操作模式
private int mMode=Mode_None;
//当前坐标
private float mDownX,mDownY;
//存储两点间的距离
private float mDistance=0f;
//存储中点
private PointF mPoint;
float mScale=0f;

public GraffitiView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public void setFilePath(String filePath) {
    this.filePath = filePath;
    //根据原位图的大小创建一个新位图,得到的位图是可变的
    DisplayMetrics dm = getResources().getDisplayMetrics();
    originalBitmap = BitmapFactory.decodeFile(filePath).copy(Bitmap.Config.ARGB_8888, true);
    mScreenWidth = dm.widthPixels;
    int width = originalBitmap.getWidth();
    double proportion = mScreenWidth / (double) width;
    mScreenHeight = (int) (originalBitmap.getHeight() * proportion);
    //        new1Bitmap = Bitmap.createBitmap(originalBitmap);  //得到一个不可变位图
    //finalBitmap = Bitmap.createScaledBitmap(originalBitmap, mScreenWidth, mScreenHeight, true);
    finalBitmap = Bitmap.createScaledBitmap(originalBitmap, mScreenWidth, mScreenHeight, true);
    list.add(finalBitmap);
    setImageBitmap(finalBitmap);
    mMatrix=new Matrix();
}

@Override
protected void onDraw(Canvas canvas) {
    //消除图像锯齿
    canvas.setDrawFilter(new PaintFlagsDrawFilter(0,Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG));
    canvas.save();
    switch (drawType) {
        case 0:
            canvas.drawBitmap(handWriting(), mMatrix, null);
            break;
        case 1:
            canvas.drawBitmap(drawOval(), mMatrix, null);
            break;
        case 2:
            canvas.drawBitmap(drawRect(), mMatrix, null);
            break;
        case 3:
            canvas.drawBitmap(drawArrow(), mMatrix, null);
            break;
        case 4:
            canvas.drawBitmap(writeText(), mMatrix, null);
            break;
    }
    canvas.restore();
}

/**
 * 画线条
 *
 * @return
 */
public Bitmap handWriting() {
    if (isClear) {
        isClear = false;
        finalBitmap = newBitmap;
        return finalBitmap;
    } else {
        Bitmap bitmap = Bitmap.createScaledBitmap(finalBitmap, mScreenWidth, mScreenHeight, true);
        Canvas canvas = new Canvas(bitmap);
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStrokeWidth(strokeWidth);
        if (isMove) {  //当移动时绘制
            canvas.drawLine(startX, startY, clickX, clickY, paint);  //在画布上画线(通过起点、终点和画笔)
        }
        //起点需要不断变化,否则画出来的不是线而是面,因为起点一直不变
        startX = clickX;
        startY = clickY;
        finalBitmap = bitmap;
        return finalBitmap;
    }
}

/**
 * 画椭圆(包括圆,圆是一种特殊的椭圆)
 *
 * @return
 */
public Bitmap drawOval() {
    if (mMode==Mode_Zoom) {
        return finalBitmap;
    }
    if (isClear) {
        isClear = false;
        finalBitmap = newBitmap;
        return finalBitmap;
    } else {
        Bitmap bitmap = Bitmap.createScaledBitmap(finalBitmap, mScreenWidth, mScreenHeight, true);
        Canvas canvas = new Canvas(bitmap);
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStrokeWidth(strokeWidth);
        if (isMove) {
            canvas.drawOval(new RectF(startX, startY, clickX, clickY), paint);
        }
        finalOvalBitmap = bitmap;
        return finalOvalBitmap;
    }
}

/**
 * 画矩形
 *
 * @return
 */
public Bitmap drawRect() {
    if (mMode==Mode_Zoom) {
        return finalBitmap;
    }
    if (isClear) {
        isClear = false;
        finalBitmap = newBitmap;
        return finalBitmap;
    } else {
        Bitmap bitmap = Bitmap.createScaledBitmap(finalBitmap, mScreenWidth, mScreenHeight, true);
        Canvas canvas = new Canvas(bitmap);
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStrokeWidth(strokeWidth);
        if (isMove) {
            canvas.drawRect(startX, startY, clickX, clickY, paint);
        }
        finalRectBitmap = bitmap;
        return finalRectBitmap;
    }
}

/**
 * 画箭头
 */
public Bitmap drawArrow() {
    if (isClear) {
        isClear = false;
        finalBitmap = newBitmap;
        return finalBitmap;
    } else {
        Bitmap bitmap = Bitmap.createScaledBitmap(finalBitmap, mScreenWidth, mScreenHeight, true);
        Canvas canvas = new Canvas(bitmap);
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(color);
        paint.setStrokeWidth(strokeWidth);
        if (isMove) {
            drawArrow(startX, startY, clickX, clickY, canvas, paint);
        }
        finalArrowBitmap = bitmap;
        return finalArrowBitmap;
    }
}

public void drawArrow(float startX, float startY, float endX, float endY, Canvas canvas, Paint paint) {
    double H = 10;  //箭头高度
    double L = 6;  //底边的一半
    int x3 = 0;
    int y3 = 0;
    int x4 = 0;
    int y4 = 0;
    double awrad = Math.atan(L / H);  //箭头角度
    double arraow_len = Math.sqrt(L * L + H * H);  //箭头的长度
    double[] arrXY_1 = rotateVec(endX - startX, endY - startY, awrad, true, arraow_len);
    double[] arrXY_2 = rotateVec(endX - startX, endY - startY, -awrad, true, arraow_len);
    double x_3 = endX - arrXY_1[0];  //(x3,y3)是第一端点
    double y_3 = endY - arrXY_1[1];
    double x_4 = endX - arrXY_2[0];  //(x4,y4)是第二端点
    double y_4 = endY - arrXY_2[1];
    Double X3 = new Double(x_3);
    x3 = X3.intValue();
    Double Y3 = new Double(y_3);
    y3 = Y3.intValue();
    Double X4 = new Double(x_4);
    x4 = X4.intValue();
    Double Y4 = new Double(y_4);
    y4 = Y4.intValue();
    //画线
    canvas.drawLine(startX, startY, endX, endY, paint);
    Path triangle = new Path();
    triangle.moveTo(endX, endY);
    triangle.lineTo(x3, y3);
    triangle.lineTo(x4, y4);
    triangle.close();
    canvas.drawPath(triangle, paint);
}

public double[] rotateVec(float px, float py, double ang, boolean isChLen, double newLen) {
    double mathstr[] = new double[2];
    //矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
    double vx = px * Math.cos(ang) - py * Math.sin(ang);
    double vy = px * Math.sin(ang) + py * Math.cos(ang);
    if (isChLen) {
        double d = Math.sqrt(vx * vx + vy * vy);
        vx = vx / d * newLen;
        vy = vy / d * newLen;
        mathstr[0] = vx;
        mathstr[1] = vy;
    }
    return mathstr;
}

/**
 * 在图片上写字
 *
 * @param text
 */
public void writeTextToBitmap(String text) {
    drawType = 4;
    this.text = text;
    invalidate();
}

public Bitmap writeText() {
    if (isClear) {
        isClear = false;
        finalBitmap = newBitmap;
        finalTextBitmap = finalBitmap;
        return finalBitmap;
    } else {
        Bitmap bitmap = Bitmap.createScaledBitmap(finalBitmap, mScreenWidth, mScreenHeight, true);
        Canvas canvas = new Canvas(bitmap);
        TextPaint textPaint = new TextPaint();
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize * getResources().getDisplayMetrics().density);
        textPaint.setAntiAlias(true);
        StaticLayout staticLayout = new StaticLayout(text, textPaint, mScreenWidth * 3 / 4, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
        canvas.translate(clickX, clickY);
        staticLayout.draw(canvas);
        finalTextBitmap = bitmap;
        return finalTextBitmap;
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    clickX = event.getX();
    clickY = event.getY();
    int action = event.getAction();
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        //当按下并不移动时,刷新并记下按下时的坐标点但不绘制
        mMode=Mode_Drag;
        startX = clickX;
        startY = clickY;
        isMove = false;
        invalidate();
        return true;
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        //当移动时,进行绘制,从按下的坐标点起
        //缩放处理
        if(mMode==Mode_Zoom)
        {
            mResultMatrix.set(mSavedMatrix);
            //获取缩放比率

            try {
                mScale=getDistance(event)/mDistance;
            } catch (Exception e) {

            }

            //获取旋转角,这里可以不用
            //float Angle=getAngle(Event)-mAngle;
            //以中点为中心,进行缩放
            mResultMatrix.postScale(mScale, mScale, mPoint.x, mPoint.y);
            //以中点为中心,进行旋转,这里可以不用
            //mResultMatrix.postRotate(Angle, mPoint.x, mPoint.y);
            mMatrix.set(mResultMatrix);
        } else if (mMode==Mode_Drag){
            if (isEdit) {
                isMove = true;
            }
        }
        invalidate();
        return true;
    } else if (event.getAction() == MotionEvent.ACTION_UP && mMode == Mode_Drag) {
        isMove = false;
        switch (drawType) {
            case 1:
                finalBitmap = finalOvalBitmap;
                break;
            case 2:
                finalBitmap = finalRectBitmap;
                break;
            case 3:
                finalBitmap = finalArrowBitmap;
                break;
        }
        list.add(finalBitmap);
        return true;
    } else if (MotionEvent.ACTION_POINTER_1_DOWN == event.getAction() || MotionEvent.ACTION_POINTER_2_DOWN == event.getAction() || MotionEvent.ACTION_POINTER_3_DOWN == event.getAction()) {
        mMode=Mode_Zoom;
        //获取两点间距离
        mDistance=getDistance(event);
        //获取中点
        mPoint=getMidPoint(event);
        mSavedMatrix.set(mMatrix);
        isMove = false;
        return true;
    } else if (event.getAction() == MotionEvent.ACTION_POINTER_UP) {
        mMode = Mode_None;
    }
    return super.onTouchEvent(event);
}


//返回两点间的距离
public float getDistance(MotionEvent Event)
{
    //计算X的变化量
    float DeltalX=Event.getX(0)-Event.getX(1);
    //计算Y的变化量
    float DeltalY=Event.getY(0)-Event.getY(1);
    //计算距离
    return (float)Math.sqrt(DeltalX*DeltalX+DeltalY*DeltalY);
}

//返回两点的中点
public PointF getMidPoint(MotionEvent Event)
{
    float X=Event.getX(0)+Event.getX(1);
    float Y=Event.getY(0)+Event.getY(1);
    return new PointF(X/2,Y/2);
}

//获得旋转角
public float getAngle(MotionEvent Event)
{
    double DeltalX=Event.getX(0)-Event.getX(1);
    double DeltalY=Event.getY(0)-Event.getY(1);
    return (float)Math.atan2(DeltalX, DeltalY);
}

/**
 * 设置画的类型
 *
 * @param drawType
 */
public void setDrawType(int drawType) {
    if (this.drawType == 4) {
        finalBitmap = finalTextBitmap;
    }
    this.drawType = drawType;
}

/**
 * 恢复原图大小
 */
public void setRestore() {
    mMatrix = new Matrix();
    invalidate();
}

/**
 *设置撤回
 */
public void setWithdraw() {
    if (list.size() > 1) {
        finalBitmap = list.get(list.size() - 2);
        setImageBitmap(finalBitmap);
        list.remove(list.size() - 1);
    }
}

/**
 * 设置是否允许对图片进行编辑
 *
 * @param isEdit
 */
public void setIdEdit(boolean isEdit) {
    this.isEdit = isEdit;
}

/**
 * 清空
 */
public void clear() {
    isClear = true;
    newBitmap = Bitmap.createScaledBitmap(originalBitmap, mScreenWidth, mScreenHeight, true);
    invalidate();
}

/**
 * 设置画笔颜色
 *
 * @param color
 */
public void setColor(int color) {
    this.color = color;
}

/**
 * 设置画笔的宽度
 *
 * @param strokeWidth
 */
public void setStyle(float strokeWidth) {
    this.strokeWidth = strokeWidth;
}

/**
 * 设置字体大小
 *
 * @param textSize
 */
public void setTextSize(int textSize) {
    this.textSize = textSize;
}

/**
 * 设置字体颜色
 *
 * @param textColor
 */
public void setTextColor(int textColor) {
    this.textColor = textColor;
}

/**
 * 保存图片
 */
public void saveBitmap(Handler handler) {
    if (drawType == 4) {
        finalBitmap = finalTextBitmap;
    }
    if (!filePath.equals(Environment.getExternalStorageDirectory().getPath() + "/JCamera/image.jpeg")) {
        int bitmapWidth = originalBitmap.getWidth();
        int bitmapHeight = originalBitmap.getHeight();
        finalBitmap = Bitmap.createScaledBitmap(finalBitmap, mScreenWidth, mScreenHeight, true);
    }
    FileOutputStream fos = null;
    try {
        fos = new FileOutputStream(filePath);
        finalBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
        fos.flush();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        handler.sendMessage(Message.obtain());
    }
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值