1、PaintViewActivity
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import com.HBuilder.integrate.PaintIt.PaintView;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
public class PaintViewActivity extends Activity implements View.OnClickListener,View.OnLongClickListener {
private Bitmap bitmap;
private PaintView paintView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_paint_view);
paintView = findViewById(R.id.paintView);
final String iPath = this.getIntent().getStringExtra("url");
//为了下载图片资源,开辟一个新的子线程
Thread t=new Thread(){
public void run() {
//下载图片的路径
try {
//对资源链接
URL url=new URL(iPath);
//打开输入流
InputStream inputStream=url.openStream();
//对网上资源进行下载转换位图图片
bitmap=BitmapFactory.decodeStream(inputStream);
paintView.initBitmap(bitmap);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
};
};
t.start();
findViewById(R.id.paint).setOnClickListener(this);
findViewById(R.id.text).setOnClickListener(this);
findViewById(R.id.back).setOnClickListener(this);
findViewById(R.id.clear).setOnClickListener(this);
findViewById(R.id.save).setOnClickListener(this);
findViewById(R.id.move).setOnClickListener(this);
findViewById(R.id.zoom).setOnClickListener(this);
findViewById(R.id.reset).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.paint:
// use paint
paintView.paint();
break;
case R.id.text:
// use paint
paintView.text();
break;
case R.id.back:
// use paint
paintView.back();
break;
case R.id.clear:
// use paint
paintView.Clear();
break;
case R.id.save:
// use paint
paintView.save();
break;
case R.id.move:
// use paint
paintView.move();
break;
case R.id.zoom:
// use paint
paintView.zoom();
break;
case R.id.reset:
// use paint
paintView.reset();
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
@Override
public boolean onLongClick(View v) {
return true;
}
@Override
public void onBackPressed() {
paintView.showCustomToast("返回");
finish();
//TODO something
super.onBackPressed();
}
}
2、PaintView
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Environment;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.HBuilder.integrate.R;
import com.HBuilder.integrate.TextNode;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
* Package com.hc.studyview
* Created by HuaChao on 2016/6/3.
*/
public class PaintView extends View {
private Context context;
private boolean isPaint = false;//空心正方形
private boolean isText = false;//文字
private boolean isMove = true;//移动
private boolean isZoom = false;//缩放
private Paint mPaint;//画笔
private Bitmap originalBitmap;//原始图片
private Bitmap bitmap;//处理后图片
private List originalGraphical; //原始图形
private float rX, rY;//矩形起点
private float x1,y1,x2,y2;//手指移动矩形坐标
private float x3,y3;//图形移动起始坐标
private int currentLeft,currentTop;//当前图形偏移量
private Rect mSrcRect, mDestRect;//图片绘画区域
private double nLenStart;//缩放起始长度
private double zoom=1;//缩放比例
private int fontSize = 50;
public PaintView(Context context) {
super(context);
this.context = context;
this.originalGraphical = new ArrayList<>();
this.mPaint = new Paint();
}
public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
this.originalGraphical = new ArrayList<>();
this.mPaint = new Paint();
}
//切换至矩形绘图
public void paint(){
showCustomToast("矩形");
isPaint = true;
isText = false;
isMove = false;
isZoom = false;
}
//矩形坐标填充
private void rectPoint(float x,float y){
x1 = rX>x?x:rX;
y1 = rY>y?y:rY;
x2 = rX0){
originalGraphical.remove(originalGraphical.size()-1);
invalidate();
}
}
//清空
public void Clear(){
showCustomToast("清空");
isPaint = false;
isText = false;
isMove = false;
isZoom = false;
originalGraphical.clear();
invalidate();
}
//切换至移动图片
public void move(){
showCustomToast("移动");
isPaint = false;
isText = false;
isMove = true;
isZoom = false;
}
//图形移动偏移量计算
private void img_move(float x,float y){
int moveLeft = x>x3?15:-15;
int moveTop = y>y3?15:-15;
currentLeft = currentLeft + moveLeft;
currentTop = currentTop + moveTop;
x3 = x;
y3 = y;
}
//缩放
public void zoom(){
showCustomToast("缩放");
isPaint = false;
isText = false;
isMove = false;
isZoom = true;
}
public void reset(){
showCustomToast("复原");
isPaint = false;
isText = false;
isMove = false;
isZoom = false;
zoom =1;
invalidate();
}
//缩放比例计算
private void zoomComputer(MotionEvent event){
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN ){
int xlen = Math.abs((int) event.getX(0) - (int) event.getX(1));
int ylen = Math.abs((int) event.getY(0) - (int) event.getY(1));
nLenStart = Math.sqrt((double) xlen * xlen + (double) ylen * ylen);
} else {
int xlen = Math.abs((int) event.getX(0) - (int) event.getX(1));
int ylen = Math.abs((int) event.getY(0) - (int) event.getY(1));
double nLenEnd = Math.sqrt((double) xlen * xlen + (double) ylen * ylen);
double f = nLenEnd / nLenStart;
if (f != 1) {
zoom += (f > 1 ? +0.02 : -0.02);
}
if (zoom > 2) {
zoom = 2;
}
if (zoom < 0.5) {
zoom = 0.5;
}
}
}
//图片绘画计算
public void bitmapTranslate() {
Matrix matrix = new Matrix();
matrix.setScale((float)zoom,(float)zoom);
bitmap = Bitmap.createBitmap(originalBitmap, 0, 0, originalBitmap.getWidth(), originalBitmap.getHeight(), matrix, true);
mSrcRect.right = bitmap.getWidth();
mSrcRect.bottom = bitmap.getHeight();
mDestRect.left = currentLeft;
mDestRect.right = currentLeft + bitmap.getWidth();
mDestRect.top = currentTop;
mDestRect.bottom = currentTop + bitmap.getHeight();
}
//矩形绘画计算
private Rect rectTranslate(Rect rect){
return new Rect((int)(rect.left*zoom+currentLeft),(int)(rect.top*zoom+currentTop),(int)(rect.right*zoom+currentLeft),(int)(rect.bottom*zoom+currentTop));
}
//文字绘画机选
private TextNode textTranslate(TextNode textNode){
return new TextNode(textNode.getText(),(float) (textNode.getLeft()*zoom+currentLeft),(float)( textNode.getTop()*zoom+currentTop));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(bitmap!=null){
bitmapTranslate();
canvas.drawBitmap(bitmap,mSrcRect, mDestRect,mPaint );
}
for(Object o : originalGraphical) {
if (o instanceof Rect) {
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(rectTranslate((Rect)o) , mPaint);
} else if (o instanceof TextNode) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize((int)(fontSize*zoom));
TextNode t = textTranslate((TextNode)o);
canvas.drawText(t.getText(),t.getLeft(), t.getTop(), mPaint);
}
}
//手指移动绘制矩形
if(isPaint) {
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(x1, y1, x2, y2, mPaint);
}
//canvas.drawPath(mPath, mEraserPaint);
}
// 初始化画笔
private void Init_Paint(int color ,int width){
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(color);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(width);
}
//提示框
public void showCustomToast(String toast) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(R.layout.toast_item, (ViewGroup)findViewById(R.id.toast_item));
TextView text = (TextView) view.findViewById(R.id.toast_text);
text.setText(toast);
Toast tempToast = new Toast(context);
tempToast.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.CENTER, 0, 0);
tempToast.setDuration(Toast.LENGTH_SHORT);
tempToast.setView(view);
tempToast.show();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int nCnt = event.getPointerCount();
if(nCnt==2){
isMove = false;
isPaint = false;
isText = false;
zoomComputer(event);
isMove = true;
invalidate();
return true;
}
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_down(x, y);
break;
case MotionEvent.ACTION_MOVE:
touch_move(x,y);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up(x,y);
invalidate();
break;
}
return true;
}
//手指按下
private void touch_down(float x, float y) {
if(isPaint){
this.rX = x;
this.rY = y;
}
}
//手指移动
private void touch_move(float x, float y) {
if(isPaint){
rectPoint(x,y);
}else if(isMove){
img_move(x,y);
}
}
//手指弹起
private void touch_up(final float x,final float y){
if(isPaint){
rectPoint(x,y);
Rect r = new Rect((int)(x1/zoom-currentLeft/zoom),(int)(y1/zoom-currentTop/zoom),(int)(x2/zoom-currentLeft/zoom),(int)(y2/zoom-currentTop/zoom));
originalGraphical.add(r);
}else if(isText){
edit(x,y);
}
}
//初始化图片
public void initBitmap(Bitmap bitmap) {
Init_Paint(UserInfo.PaintColor, UserInfo.PaintWidth);
this.bitmap = bitmap;
this.originalBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), new Matrix(), true);
mSrcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
mDestRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
invalidate();
}
//保存图片
public void save() {
Bitmap copyBitmap = Bitmap.createBitmap(originalBitmap.getWidth(), originalBitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(copyBitmap);
c.drawBitmap(originalBitmap,new Matrix(),mPaint);
for(Object o : originalGraphical) {
if (o instanceof Rect) {
mPaint.setStyle(Paint.Style.STROKE);
c.drawRect((Rect) o, mPaint);
} else if (o instanceof TextNode) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(fontSize);
TextNode t = (TextNode)o;
c.drawText(t.getText(),t.getLeft(),t.getTop(), mPaint);
}
}
FileOutputStream fos;
String imagePath = "";
try {
// 判断手机设备是否有SD卡
boolean isHasSDCard = Environment.getExternalStorageState().equals(
android.os.Environment.MEDIA_MOUNTED);
if (isHasSDCard) {
// SD卡根目录
File sdRoot = Environment.getExternalStorageDirectory();
File file = new File(sdRoot, Calendar.getInstance().getTimeInMillis()+".png");
fos = new FileOutputStream(file);
imagePath = file.getAbsolutePath();
showCustomToast(file.getPath());
} else
throw new Exception("创建文件失败!");
copyBitmap.compress(Bitmap.CompressFormat.PNG, 90, fos);
fos.flush();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
this.destroyDrawingCache();
}
}
3、TextNode
import android.app.Application;
import java.util.ArrayList;
/**
* Created by liufengkai on 15/8/25.
*/
public class PathNode extends Application {
public class Node {
public Node() {
}
public float x;
public float y;
public int PenColor;
public int TouchEvent;
public int PenWidth;
public boolean IsPaint;
public long time;
public int EraserWidth;
}
private ArrayList PathList;
public ArrayList getPathList() {
return PathList;
}
public void addNode(Node node) {
PathList.add(node);
}
public Node NewAnode() {
return new Node();
}
public void clearList() {
PathList.clear();
}
@Override
public void onCreate() {
super.onCreate();
PathList = new ArrayList();
}
public void setPathList(ArrayList pathList) {
PathList = pathList;
}
public Node getTheLastNote() {
return PathList.get(PathList.size() - 1);
}
public void deleteTheLastNote() {
PathList.remove(PathList.size() - 1);
}
public PathNode() {
PathList = new ArrayList<>();
}
}
4、layout布局文件