1. 下载图片

  public Runnable saveFileRunnable = new Runnable() {@Overridepublic void run() {try {if (!TextUtils.isEmpty(filePath)) { //网络图片// 对资源链接URL url = new URL(filePath);//打开输入流InputStream inputStream = url.openStream();//对网上资源进行下载转换位图图片mBitmap = BitmapFactory.decodeStream(inputStream);
//                    mBitmap = zoomImg(mBitmap, 1920, 1104);//设置修改图片大小mBitmap = zoomImg(mBitmap, mBitmap.getWidth()*2, mBitmap.getHeight()*2);inputStream.close();}saveFile(mBitmap);mSaveMessage = "图片保存成功!";} catch (IOException e) {mSaveMessage = "图片保存失败!";e.printStackTrace();} catch (Exception e) {e.printStackTrace();}messageHandler.sendMessage(messageHandler.obtainMessage());}};private Handler messageHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {Log.i("pathq",""+pathq);}};

2. 加载画板

    private ArrayList<Word> words = new ArrayList<Word>();private ArrayList<CirclePath> circlePaths = new ArrayList<CirclePath>();private ArrayList<RectPath> rectPaths = new ArrayList<RectPath>();private ArrayList<OvalPath> ovalPaths = new ArrayList<OvalPath>();private ArrayList<ArrowPath> arrowPaths = new ArrayList<ArrowPath>();private ArrayList<LinexuPath> linexuPaths = new ArrayList<LinexuPath>();private ArrayList<LinexuPath> linezhiPaths = new ArrayList<LinexuPath>();private ArrayList<LinePath> linePaths = new ArrayList<LinePath>();private ArrayList<XuPath> XuPaths = new ArrayList<XuPath>();private boolean canDraw;private PopupWindow popupWindow;private LinePath currentLinPath;private XuPath xuLinPath;private CirclePath currentCirclePath;private RectPath currentRectPath;private OvalPath currentOvalPath;private ArrowPath currentArrowPath;private LinexuPath linexuPath;private Paint mPaint;private Path mPathssa;private Path mPath;private Matrix matrix = new Matrix();private GestureDetector detector;public CameraSurfaceView(Context context) {super(context);init(context);}public CameraSurfaceView(Context context, AttributeSet attrs) {super(context, attrs);init(context);}public CameraSurfaceView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);}private void init(Context context) {paint = new Paint();paint.setColor(Color.RED);paint.setStrokeWidth(2);paint.setStyle(Style.STROKE);paint.setTextSize(25);paint.setAntiAlias(true);detector = new GestureDetector(listener);}private Paint eraserPaint;private boolean isEraserModel;private SimpleOnGestureListener listener = new SimpleOnGestureListener() {public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {float[] value = new float[9];matrix.getValues(value);float maxTranX = mBitmap.getWidth() * value[Matrix.MSCALE_X] - getWidth();float maxTranY = mBitmap.getHeight() * value[Matrix.MSCALE_X] - getHeight();if (value[Matrix.MSCALE_X] >= MIN_SCALE) {float dx = -distanceX + value[Matrix.MTRANS_X];//计算出实际会偏移的量float dy = -distanceY + value[Matrix.MTRANS_Y];if (dx > 0) {//如果实际量超出边框就就把相对偏移量为零dx = 0;} else if (-dx > maxTranX) {dx = 0;} else {dx = -distanceX;}if (dy > 0) {dy = 0;} else if (-dy > maxTranY) {dy = 0;} else {dy = -distanceY;}matrix.postTranslate(dx, dy);Log.i(TAG, "onScroll" + dx + ":" + dy + "mBitmap.getHeight()" + mBitmap.getHeight() + "value[Matrix.MSCALE_X]" + value[Matrix.MSCALE_X]);post(CameraSurfaceView.this);return true;}return false;}public boolean onDoubleTap(MotionEvent e) {Log.i(TAG, "onDoubleTap");float[] value = new float[9];matrix.getValues(value);if (value[Matrix.MSCALE_X] > MIN_SCALE) {matrix.reset();} else {float px = e.getX();float py = e.getY();float sx = MAX_SCALE / value[Matrix.MSCALE_X];float sy = MAX_SCALE / value[Matrix.MSCALE_Y];matrix.postScale(sx, sy, px, py);}post(CameraSurfaceView.this);return true;}};private float mOldDist = 0;@SuppressLint("ClickableViewAccessibility")@Overridepublic boolean onTouchEvent(MotionEvent event) {if (canDraw) {switch (currentDraw) {case DRAW_PATH:lineEvevn(event);break;case DRAW_WORD:wordEven(event);break;case DRAW_CIRCLE:circleEvent(event);break;case DRAW_RECT:rectEvent(event);break;case DRAW_ARROW:arrowEvent(event);break;case DRAW_OVAL:ovalEvent(event);break;case DRAW_NOTHING:if (!nothingEvent(event)) {detector.onTouchEvent(event);}break;case xu:ovalEvent2(event);break;case zhi:ovalEvent3(event);break;case zhilin :ovalEvent4(event);break;default:break;}return true;}return super.onTouchEvent(event);}private void ovalEvent2(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mPathssa = new Path();event.getX();xuLinPath = new XuPath(new Path(), new Paint(paint));xuLinPath.getPath().moveTo(event.getX(), event.getY());pathTo2(event);break;case MotionEvent.ACTION_MOVE:xuLinPath.getPath().lineTo(event.getX(), event.getY());pathTo2(event);break;case MotionEvent.ACTION_UP:pathTo2(event);xuLinPath.setPath(mPathssa);XuPaths.add(xuLinPath);xuLinPath = null;mPathssa = null;break;default:break;}post(this);}private void ovalEvent3(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mPathssa = new Path();Paint cPaint = new Paint(paint);linexuPath = new LinexuPath((int) event.getX(), (int) event.getY(), (int) event.getX() + 1, (int) event.getY() + 1, cPaint);
//                linexuPath.getPath().moveTo(event.getX(), event.getY());//                pathTo3(event);break;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();linexuPath.seteX((int) mX);linexuPath.seteY((int) mY);break;case MotionEvent.ACTION_UP:float uX = event.getX();float uY = event.getY();linexuPath.seteX((int) uX);linexuPath.seteY((int) uY);linexuPath.reset(matrix);linexuPaths.add(linexuPath);linexuPath = null;break;default:break;}post(this);}private void ovalEvent4(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mPathssa = new Path();Paint cPaint = new Paint(paint);linexuPath = new LinexuPath((int) event.getX(), (int) event.getY(), (int) event.getX() + 1, (int) event.getY() + 1, cPaint);
//                linexuPath.getPath().moveTo(event.getX(), event.getY());pathTo3(event);break;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();linexuPath.seteX((int) mX);linexuPath.seteY((int) mY);pathTo3(event);break;case MotionEvent.ACTION_UP:float uX = event.getX();float uY = event.getY();linexuPath.seteX((int) uX);linexuPath.seteY((int) uY);linexuPath.reset(matrix);linezhiPaths.add(linexuPath);linexuPath = null;break;default:break;}post(this);}/*** 缩放处理** @param event* @return*/private boolean nothingEvent(MotionEvent event) {int count = event.getPointerCount();if (count > 1) {int action = event.getAction();action = action & MotionEvent.ACTION_MASK;switch (action) {case MotionEvent.ACTION_POINTER_DOWN:Log.i(TAG, "ACTION_DOWN");mOldDist = getDistOfTowPoints(event);break;case MotionEvent.ACTION_MOVE:Log.i(TAG, "ACTION_MOVE");float mNewDist = getDistOfTowPoints(event);if (Math.abs(mNewDist - mOldDist) > 50) {float[] value = new float[9];matrix.getValues(value);Log.i(TAG, "偏移量" + value[Matrix.MTRANS_X] + ":" + value[Matrix.MTRANS_Y]);float scale = value[Matrix.MSCALE_X];//原来的放缩量float px = (event.getX(0) + event.getX(1)) / 2;float py = (event.getY(0) + event.getY(1)) / 2;if (mOldDist > mNewDist) {scale -= Math.abs(mNewDist - mOldDist) / 500f;//计算现在的放缩量Log.i(TAG, "缩小" + scale + ":" + Math.abs(mNewDist -mOldDist));} else {scale += Math.abs(mNewDist - mOldDist) / 500f;//计算现在的放缩量// Log.i(TAG, "放大" + scale);}if (scale < MIN_SCALE) {//如果放缩量小于最低的就置为最低放缩比scale = MIN_SCALE;} else if (scale > MAX_SCALE) {//如果放缩量大于最高的就置为最高放缩比scale = MAX_SCALE;}if (scale == MIN_SCALE) {//如果放缩量为最小就把矩阵重置matrix.reset();} else {scale = scale / value[Matrix.MSCALE_X];//计算出相对的放缩量,使矩阵的放缩量为放缩到计算出来的放缩量。matrix.postScale(scale, scale, px, py);}Log.i(TAG, "" + scale / value[Matrix.MSCALE_X] + ":" + Math.abs(mNewDist - mOldDist));mOldDist = mNewDist;post(this);}break;default:break;}return true;}return false;}/*** 获取两点之间的距离** @return int 返回两点间的距离*/private float getDistOfTowPoints(MotionEvent event) {float x0 = event.getX(0);float y0 = event.getY(0);float x1 = event.getX(1);float y1 = event.getY(1);float lengthX = Math.abs(x0 - x1);float lengthY = Math.abs(y0 - y1);return (float) Math.sqrt(lengthX * lengthX + lengthY * lengthY);}/*** 当画椭圆时** @param event*/private void ovalEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Paint cPaint = new Paint(paint);RectF rectF = new RectF(event.getX(), event.getY(), event.getX() + 1, event.getY() + 1);currentOvalPath = new OvalPath(rectF, cPaint);break;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();currentOvalPath.getRectF().right = mX;currentOvalPath.getRectF().bottom = mY;break;case MotionEvent.ACTION_UP:float uX = event.getX();float uY = event.getY();currentOvalPath.getRectF().right = uX;currentOvalPath.getRectF().bottom = uY;currentOvalPath.reset(matrix);ovalPaths.add(currentOvalPath);currentOvalPath = null;break;default:break;}post(this);}/*** 当画箭头** @param event*/private void arrowEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Paint cPaint = new Paint(paint);currentArrowPath = new ArrowPath((int) event.getX(), (int) event.getY(), (int) event.getX() + 1, (int) event.getY() + 1, cPaint);break;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();currentArrowPath.seteX((int) mX);currentArrowPath.seteY((int) mY);break;case MotionEvent.ACTION_UP:float uX = event.getX();float uY = event.getY();currentArrowPath.seteX((int) uX);currentArrowPath.seteY((int) uY);currentArrowPath.reset(matrix);arrowPaths.add(currentArrowPath);currentArrowPath = null;break;default:break;}post(this);}/*** 画方** @param event*/private void rectEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:currentRectPath = new RectPath();Paint cPaint = new Paint(paint);currentRectPath.setPaint(cPaint);currentRectPath.setLeft(event.getX());currentRectPath.setTop(event.getY());currentRectPath.setRight(event.getX() + 1);currentRectPath.setBottom(event.getY() + 1);break;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();currentRectPath.setRight(mX);currentRectPath.setBottom(mY);break;case MotionEvent.ACTION_UP:float uX = event.getX();float uY = event.getY();currentRectPath.setRight(uX);currentRectPath.setBottom(uY);currentRectPath.reset(matrix);rectPaths.add(currentRectPath);currentRectPath = null;break;default:break;}post(this);}/*** 画圆** @param event*/private void circleEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:currentCirclePath = new CirclePath();currentCirclePath.setCx(event.getX());currentCirclePath.setCy(event.getY());currentCirclePath.setRadius(1);Paint cPaint = new Paint(paint);currentCirclePath.setPaint(cPaint);break;case MotionEvent.ACTION_MOVE:float mX = event.getX();float mY = event.getY();float r = (float) Math.sqrt(Math.pow(Math.abs(mX - currentCirclePath.getCx()), 2) + Math.pow(Math.abs(mY - currentCirclePath.getCy()), 2));currentCirclePath.setRadius(r);break;case MotionEvent.ACTION_UP:float uX = event.getX();float uY = event.getY();float ur = (float) Math.sqrt(Math.pow(Math.abs(uX - currentCirclePath.getCx()), 2) + Math.pow(Math.abs(uY - currentCirclePath.getCy()), 2));currentCirclePath.setRadius(ur);currentCirclePath.reset(matrix);circlePaths.add(currentCirclePath);currentCirclePath = null;break;default:break;}post(this);}/*** 写字** @param event*/private void wordEven(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.i(TAG, "DRAW_WORD+ACTION_DOWN");showPop((int) event.getX(), (int) event.getY());break;default:break;}}/*** 划线** @param event*/private void lineEvevn(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mPath = new Path();currentLinPath = new LinePath(new Path(), new Paint(paint));currentLinPath.getPath().moveTo(event.getX(), event.getY());pathTo(event);break;case MotionEvent.ACTION_MOVE:currentLinPath.getPath().lineTo(event.getX(), event.getY());pathTo(event);break;case MotionEvent.ACTION_UP:pathTo(event);currentLinPath.setPath(mPath);linePaths.add(currentLinPath);currentLinPath = null;mPath = null;break;default:break;}post(this);}private void pathTo(MotionEvent event) {Point pointD = new Point((int) event.getX(), (int) event.getY());calculationRealPoint(pointD, matrix);if (event.getAction() == MotionEvent.ACTION_DOWN) {mPath.moveTo(pointD.x, pointD.y);} else {mPath.lineTo(pointD.x, pointD.y);}}private void pathTo2(MotionEvent event) {Point pointD = new Point((int) event.getX(), (int) event.getY());calculationRealPoint(pointD, matrix);if (event.getAction() == MotionEvent.ACTION_DOWN) {mPathssa.moveTo(pointD.x, pointD.y);} else {mPathssa.lineTo(pointD.x, pointD.y);}}private void pathTo3(MotionEvent event) {Point pointD = new Point((int) event.getX(), (int) event.getY());calculationRealPoint(pointD, matrix);if (event.getAction() == MotionEvent.ACTION_DOWN) {mPathssa.moveTo(pointD.x, pointD.y);} else {mPathssa.lineTo(pointD.x, pointD.y);}}public void calculationRealPoint(Point point, Matrix matrix) {float[] values = new float[9];matrix.getValues(values);int sX = point.x;int sY = point.y;point.x = (int) ((sX - values[Matrix.MTRANS_X]) / values[Matrix.MSCALE_X]);point.y = (int) ((sY - values[Matrix.MTRANS_Y]) / values[Matrix.MSCALE_Y]);}/*** 显示popupWindow输入文字** @param x* @param y*/private void showPop(final float x, final float y) {if (popupWindow != null && popupWindow.isShowing()) {popupWindow.dismiss();}View contentView = View.inflate(getContext(), R.layout.popupwindow, null);final EditText etWord = (EditText) contentView.findViewById(R.id.et_word);etWord.setInputType(InputType.TYPE_CLASS_TEXT);Button btnOk = (Button) contentView.findViewById(R.id.btn_ok);btnOk.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {String word = etWord.getText().toString().trim();if (!TextUtils.isEmpty(word)) {Paint key = new Paint(paint);key.setStrokeWidth(1);key.setTypeface(Typeface.DEFAULT);key.setStyle(Style.FILL);Word wor = new Word(x, y, key, word);wor.reset(matrix);words.add(wor);post(CameraSurfaceView.this);}if (popupWindow != null && popupWindow.isShowing()) {popupWindow.dismiss();}}});popupWindow = new PopupWindow(contentView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);popupWindow.setFocusable(true);popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));// PopupWindow没有背景色,必须设置背景色popupWindow.showAtLocation(this, Gravity.TOP + Gravity.LEFT, (int) x + getLeft(), (int) y + getTop());ScaleAnimation animation = new ScaleAnimation(0.2f, 1.2f, 0.2f, 1.2f, 0.5f, 0.5f);animation.setDuration(100);// animation.setFillAfter(true);contentView.startAnimation(animation);}@Overridepublic void run() {if (mBitmap != null) {SurfaceHolder surfaceHolder = getHolder();Canvas canvas = surfaceHolder.lockCanvas();canvas.drawColor(Color.WHITE);canvas.save();canvas.setMatrix(matrix);canvas.drawBitmap(mBitmap, 0, 0, paint);//            // 指定图片绘制区域(左上角的四分之一)
//            Rect src = new Rect(0,0,1920/2,1104/2);
//            // 指定图片在屏幕上显示的区域(原图大小)
//            Rect dst = new Rect(mBitmap.getWidth()+50,0,mBitmap.getWidth()+50+mBitmap.getWidth(),mBitmap.getHeight());
//            canvas.drawBitmap(mBitmap, src,dst,null);drawText(canvas, words);drawOval(canvas, ovalPaths);drawArrow(canvas, arrowPaths);drawCircle(canvas, circlePaths);drawRect(canvas, rectPaths);drawLine(canvas, linePaths);drawxu(canvas, XuPaths);drawxian(canvas, linexuPaths);drawxian3(canvas, linezhiPaths);// canvas.save();canvas.restore();drawCurrent(canvas);surfaceHolder.unlockCanvasAndPost(canvas);}}private void drawLine(Canvas canvas, ArrayList<LinePath> linePaths2) {for (LinePath linePath : linePaths2) {canvas.drawPath(linePath.getPath(), linePath.getPaint());}}private void drawxu(Canvas canvas, ArrayList<XuPath> linePaths2) {for (XuPath linePath : linePaths2) {canvas.drawPath(linePath.getPath(), linePath.getPaint());}}private void drawxian(Canvas canvas, ArrayList<LinexuPath> linexuPath) {for (LinexuPath arrowPath : linexuPath) {drawAL1(arrowPath.getsX(), arrowPath.getsY(), arrowPath.geteX(), arrowPath.geteY(), canvas, arrowPath.getPaint());}}private void drawxian3(Canvas canvas, ArrayList<LinexuPath> linexuPath) {for (LinexuPath arrowPath : linexuPath) {drawAL1(arrowPath.getsX(), arrowPath.getsY(), arrowPath.geteX(), arrowPath.geteY(), canvas, arrowPath.getPaint());}}private void drawArrow(Canvas canvas, ArrayList<ArrowPath> arrowPaths2) {for (ArrowPath arrowPath : arrowPaths2) {drawAL(arrowPath.getsX(), arrowPath.getsY(), arrowPath.geteX(), arrowPath.geteY(), canvas, arrowPath.getPaint());}}private void drawOval(Canvas canvas, ArrayList<OvalPath> ovalPaths2) {for (OvalPath ovalPath : ovalPaths2) {canvas.drawOval(ovalPath.getRectF(), ovalPath.getPaint());}}private void drawRect(Canvas mCanvas2, ArrayList<RectPath> rectPaths2) {for (RectPath rectPath : rectPaths2) {mCanvas2.drawRect(rectPath.getLeft(), rectPath.getTop(), rectPath.getRight(), rectPath.getBottom(), rectPath.getPaint());}}private void drawCircle(Canvas mCanvas2, ArrayList<CirclePath> circlePaths2) {for (CirclePath circlePath : circlePaths2) {mCanvas2.drawCircle(circlePath.getCx(), circlePath.getCy(), circlePath.getRadius(), circlePath.getPaint());}}private void drawText(Canvas mCanvas2, ArrayList<Word> words2) {for (Word word : words2) {mCanvas2.drawText(word.getWordString(), word.getLeft(), word.getTop(), word.getPaint());}}/*** 画当前的图形** @param canvas*/private void drawCurrent(Canvas canvas) {switch (currentDraw) {case DRAW_CIRCLE:if (currentCirclePath != null) {canvas.drawCircle(currentCirclePath.getCx(), currentCirclePath.getCy(), currentCirclePath.getRadius(), currentCirclePath.getPaint());}break;case DRAW_RECT:if (currentRectPath != null) {canvas.drawRect(currentRectPath.getLeft(), currentRectPath.getTop(), currentRectPath.getRight(), currentRectPath.getBottom(), currentRectPath.getPaint());}break;case DRAW_ARROW:if (currentArrowPath != null) {drawAL(currentArrowPath.getsX(), currentArrowPath.getsY(), currentArrowPath.geteX(), currentArrowPath.geteY(), canvas, currentArrowPath.getPaint());}break;case DRAW_OVAL:if (currentOvalPath != null) {canvas.drawOval(currentOvalPath.getRectF(), currentOvalPath.getPaint());}case DRAW_PATH:if (currentLinPath != null) {canvas.drawPath(currentLinPath.getPath(), currentLinPath.getPaint());}break;case xu:if (xuLinPath != null) {DashPathEffect pathEffect = new DashPathEffect(new float[]{20, 20}, 0);xuLinPath.getPaint().setPathEffect(pathEffect);canvas.drawPath(xuLinPath.getPath(), xuLinPath.getPaint());}case zhi:if (linexuPath != null) {DashPathEffect pathEffect = new DashPathEffect(new float[]{20, 20}, 0);linexuPath.getPaint().setPathEffect(pathEffect);canvas.drawLine(linexuPath.getsX(), linexuPath.getsY(), linexuPath.geteX(), linexuPath.geteY(), linexuPath.getPaint());}break;case zhilin:if (linexuPath != null) {//                    DashPathEffect pathEffect = new DashPathEffect(new float[]{30, 30}, 0);
//
//                    linexuPath.getPaint().setPathEffect(pathEffect);canvas.drawLine(linexuPath.getsX(), linexuPath.getsY(), linexuPath.geteX(), linexuPath.geteY(), linexuPath.getPaint());}break;default:break;}}/*** 画箭头** @param sx* @param sy* @param ex* @param ey*/public void drawAL(int sx, int sy, int ex, int ey, Canvas myCanvas, Paint myPaint) {double H = 8; // 箭头高度double L = 3.5; // 底边的一半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(ex - sx, ey - sy, awrad, true, arraow_len);double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);Double X3 = ex - arrXY_1[0]; // (x3,y3)是第一端点x3 = X3.intValue();Double Y3 = ey - arrXY_1[1];y3 = Y3.intValue();Double X4 = ex - arrXY_2[0]; // (x4,y4)是第二端点x4 = X4.intValue();Double Y4 = ey - arrXY_2[1];y4 = Y4.intValue();// 画线myCanvas.drawCircle(sx, sy, 2, myPaint);// 画线myCanvas.drawLine(sx, sy, ex, ey, myPaint);Path triangle = new Path();triangle.moveTo(ex, ey);triangle.lineTo(x3, y3);triangle.lineTo(x4, y4);triangle.close();myCanvas.drawPath(triangle, myPaint);}/*** 画箭头** @param sx* @param sy* @param ex* @param ey*/public void drawAL1(int sx, int sy, int ex, int ey, Canvas myCanvas, Paint myPaint) {double H = 8; // 箭头高度double L = 3.5; // 底边的一半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(ex - sx, ey - sy, awrad, true, arraow_len);double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);Double X3 = ex - arrXY_1[0]; // (x3,y3)是第一端点x3 = X3.intValue();Double Y3 = ey - arrXY_1[1];y3 = Y3.intValue();Double X4 = ex - arrXY_2[0]; // (x4,y4)是第二端点x4 = X4.intValue();Double Y4 = ey - arrXY_2[1];y4 = Y4.intValue();// 画线myCanvas.drawLine(sx, sy, ex, ey, myPaint);
//        Path triangle = new Path();
//        triangle.moveTo(ex, ey);
//        triangle.lineTo(x3, y3);
//        triangle.lineTo(x4, y4);
//        triangle.close();
//        myCanvas.drawPath(triangle, myPaint);}/*** 矢量旋转函数,求出与结束定点的x,y距离** @param px      x分量* @param py      y分量* @param ang     旋转角度* @param isChLen 是否改变长度* @param newLen  新长度* @return*/public double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {double mathstr[] = new double[2];// double len = Math.sqrt(px*px + py*py);// double a = Math.acos(px/len);// double vx = Math.cos(a+ang)*len// double vy = Math.sin(a+ang)*lendouble 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;}public int getCurrentDraw() {return currentDraw;}public void setCurrentDraw(int currentDraw) {this.currentDraw = currentDraw;if (popupWindow != null && popupWindow.isShowing()) {popupWindow.dismiss();}}/*** 返回一个画完的图片** @return*/public Bitmap getmBitmap() {mCanvas = new Canvas(mBitmap);drawText(mCanvas, words);drawCircle(mCanvas, circlePaths);drawRect(mCanvas, rectPaths);drawArrow(mCanvas, arrowPaths);drawOval(mCanvas, ovalPaths);drawLine(mCanvas, linePaths);drawxu(mCanvas, XuPaths);drawxian(mCanvas, linexuPaths);drawxian3(mCanvas, linezhiPaths);return mBitmap;}public void setmBitmap(Bitmap mBitmap) {this.mBitmap = mBitmap;// mCanvas = new Canvas(this.mBitmap);// reset();post(this);}//// public void reset() {// if (bitmap != null) {// bitmap.recycle();// }// bitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(),// mBitmap.getWidth());// dCanvas = new Canvas(bitmap);// }public boolean isCanDraw() {return canDraw;}public void setCanDraw(boolean canDraw) {this.canDraw = canDraw;}/*** 清除对应的类型的最新的一个图形*/public void back() {switch (currentDraw) {case DRAW_CIRCLE:if (circlePaths.size() - 1 >= 0) {circlePaths.remove(circlePaths.size() - 1);}break;case DRAW_RECT:if (rectPaths.size() - 1 >= 0) {rectPaths.remove(rectPaths.size() - 1);}break;case DRAW_WORD:if (words.size() - 1 >= 0) {words.remove(words.size() - 1);}break;case DRAW_PATH:if (linePaths.size() - 1 >= 0) {linePaths.remove(linePaths.size() - 1);}break;case DRAW_ARROW:if (arrowPaths.size() - 1 >= 0) {arrowPaths.remove(arrowPaths.size() - 1);}break;case DRAW_OVAL:if (ovalPaths.size() - 1 >= 0) {ovalPaths.remove(ovalPaths.size() - 1);}break;case xu:if (XuPaths.size() - 1 >= 0) {XuPaths.remove(XuPaths.size() - 1);}break;case zhi:if (linexuPaths.size() - 1 >= 0) {linexuPaths.remove(linexuPaths.size() - 1);}break;case zhilin:if (linezhiPaths.size() - 1 >= 0) {linezhiPaths.remove(linezhiPaths.size() - 1);}break;case DRAW_NOTHING:Builder builder = new Builder(getContext());builder.setTitle("清除");builder.setMessage("是否要清除全部内容?");builder.setNegativeButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();words.clear();ovalPaths.clear();linePaths.clear();arrowPaths.clear();rectPaths.clear();circlePaths.clear();XuPaths.clear();linexuPaths.clear();linezhiPaths.clear();}}).setPositiveButton("取消", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {dialog.dismiss();}}).show();break;default:break;}post(this);}public void setTextSize(float textSize) {paint.setTextSize(textSize);}public void setColor(int color) {paint.setColor(color);}

3. demo 下载地址 https://download.csdn.net/download/qq_35742975/16343900

写了一个简单的画板 箭头比较难搞 虚线 虚直线 实线 实直线 椭圆 圆 正方形相关推荐

  1. 用java的事件监听机制实现一个简单的画板应用:通过选择图形按钮和颜色按钮来画出自己想画的图形:直线、空心矩形、圆形、折线、多边形、圆角矩形、弧线、曲线、喷枪

    今天做一个简单的画板,完整代码附在文章末尾处. - 功能:通过选择图形按钮和颜色按钮来画出自己想画的图形. - 界面展示: - 思路: 1.做一个可视化界面:创建JFrame对象,并设置Title.S ...

  2. easy-mock写的一个简单的模拟二页的反馈

    用easy-mock写的一个简单的模拟二页的反馈,因为后端团队比较传统,所以设计的结构不太规范. 功能:每页10条,共2页,共12条记录,超出参数范围会返错误码: easy模板: {code: fun ...

  3. 在iOS中实现一个简单的画板App

    在这个随笔中,我们要为iPhone实现一个简单的画板App. 首先需要指出的是,这个demo中使用QuarzCore进行绘画,而不是OpenGL.这两个都可以实现类似的功能,区别是OpenGL更快,但 ...

  4. AndroidSDK开发6我用kotlin协程写了一个简单sdk

    目录 AndroidSDK开发6我用kotlin协程写了一个简单sdk 1.kotlin的依赖和导包如下:(//如果不使用协程可以去掉协程的导包减少sdk包大小) 2.Application代码如下: ...

  5. 用shell脚本写的一个简单的俄罗斯方块

    用shell脚本写的一个简单的俄罗斯方块 代码 代码 测试 下载链接 代码 代码 #!/bin/bash #version 1.2,若非正常退出,请使用附带的killel.sh脚本杀死进程 #定义用于 ...

  6. 最近写了一个简单的面向对象的脚本语言 Q 语言

    最近写了一个简单的面向对象的脚本语言 Q 语言,语法类似于 Javascript, 加入了一些 python 的语法功能. 同时实现了部分的 Javascript prototype 的功能 (个人觉 ...

  7. 自己写的一个简单的android记事本app

    自己写的一个简单的记事本app,效果如下: 一.首先是第一个界面的编写,最上面是一个TextView,中间是一个Linearlayout中嵌套一个listview布局,最下面是一个button.下面附 ...

  8. 用li写的一个简单的横向导航菜单demo

    用ul li写的一个简单的横向导航菜单,很实用: /* 所有class为menu的div中的ul样式 */ div.menu ul { list-style:none; /* 去掉ul前面的符号 */ ...

  9. 用VB6写的一个简单俄罗斯方块代码

    网络上有很多俄罗斯方块代码.它们大都为了视觉效果,程序比较复杂,不利于学习游戏编程.所以我写了个简单俄罗斯方块代码,尽量用VB本身的功能,没有复杂的DirectX. 下载(注意修改下载后的扩展名) m ...

最新文章

  1. 后序遍历的非递归算法python_刷题系列 - Python用非递归实现二叉树后续遍历
  2. 中国7位学者当选!又一院士名单公布
  3. android 蓝牙传输分包,彻底掌握Android多分包技术(一)
  4. 昆仑通态复制的程序可以用吗_MCGS昆仑通态触摸屏
  5. SAP MTA打包的一些常见错误
  6. 分享几个接口自动化的实战练手项目
  7. 当MVP与阿里云一起踏上西行远征——阿里云MVP“戈壁之路”徒步记行
  8. Hbase CallQueueTooBigException 异常处理
  9. phpstudy mysql升级5.7
  10. PROFIBUS-DP现场总线的结构及应用
  11. mysql 三种循环的区别_mysql存储过程中的三种循环
  12. (二)VISIO 中间带箭头的弧线怎么画
  13. unity 调整画布大小_使用画布,拖放和File API调整图像大小
  14. 【附源码】计算机毕业设计SSM民宿客房管理系统
  15. RK3288 编译不过遇到的问题
  16. 测评瑞萨RZ/G2L存储读写速度与网络
  17. elasticSearch Analysis Token Filters作用及相关样例
  18. 逆向破解之破解补丁与劫持Dll
  19. 黑马训练营--IOS学习---OC语言学习总结2
  20. Android 改造无线电,浅谈Android平台的物联网网关方案设计

热门文章

  1. 使用python的PIL.Image在图片上写字
  2. 李洪强iOS开发支付集成之支付宝支付
  3. 2022软科世界大学学术排名
  4. JavaScript 推断浏览器类型及32位64位
  5. java分子分母的加减乘除_JAVA实现精确的加减乘除代码
  6. 只能看,不能读的文章
  7. FFT 快速傅里叶变换 初探
  8. 专访《突破》作者刘朋:程序员快速提升领导力的15个模式!
  9. 「苦练基本功」超级大佬推荐工程师必看的书感悟
  10. 工程师的基本功是什么?如何练习?—学习心得分享