I have a customised view for photo annotate, you can use this to do your job.
1: Create a file AnnotationView.java and copy the following code
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ImageView;
/**
* @author Bob Gao
* http://bobgao.net
*/
public class AnnotationView extends ImageView implements OnTouchListener {
private static final float KEY_STROKE_WIDTH = 4;
private List<Annotation> annotations = new ArrayList<Annotation>();
private Annotation mAnnotation;
private Canvas mCanvas;
private Paint mPaint;
// private Rect mOutRect;
public AnnotationView(Context context) {
super(context);
setOnTouchListener(this);
setDrawingCacheEnabled(true);
setScaleType(ScaleType.FIT_XY);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.mCanvas = canvas;
for (Annotation annotation : annotations) {
mPaint.setColor(annotation.getColor());
switch (annotation.getShape()) {
case Annotation.KEY_SHAPE_CIRCLE:
drawCircle(annotation.getX(), annotation.getY(), annotation.getRadius());
break;
case Annotation.KEY_SHAPE_ARROW:
drawAL((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
case Annotation.KEY_SHAPE_SQUARES:
drawRect((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius());
break;
case Annotation.KEY_SHAPE_TRIANGLE:
drawTriangle((int) annotation.getX(), (int) annotation.getY(), (int) annotation.getRadius(), annotation.getDegree());
break;
}
}
}
/**
* Draw a triangle
*
* @param x
* @param y
* @param r
*/
public void drawTriangle(int x, int y, int r, float degree) {
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x - 2 * r, y + 2 * r);
path.lineTo(x + 2 * r, y + 2 * r);
path.lineTo(x, y);
path.close();
rotatePath(path, degree);
mCanvas.drawPath(path, mPaint);
}
public void drawRect(int x, int y, int r) {
int lenght = 4 * r;
int left = x - lenght / 2;
int top = y - lenght / 2;
int right = x + lenght / 2;
int bottom = y + lenght / 2;
Path path = new Path();
path.moveTo(left, top);
path.lineTo(right, top);
path.lineTo(right, bottom);
path.lineTo(left, bottom);
path.lineTo(left, top);
path.close();
mCanvas.drawPath(path, mPaint);
}
public void drawCircle(float x, float y, float r) {
mCanvas.drawCircle(x, y, r, mPaint);
}
/**
* Draw arrow
*
* @param sx
* @param sy
* @param ex
* @param ey
*/
public void drawAL(int sx, int sy, int r, float degree) {
int ex = (int) (sx + 2 * r);
int ey = (int) (sy + 2 * r);
switch (new Float(degree).intValue()) {
case 90:
ex = (int) (sx - 2 * r);
ey = (int) (sy + 2 * r);
break;
case 180:
ex = (int) (sx - 2 * r);
ey = (int) (sy - 2 * r);
break;
case 270:
ex = (int) (sx + 2 * r);
ey = (int) (sy - 2 * r);
break;
}
double H = 8; // the height of arrow
double L = 3.5; // half of bottom line
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // the rotation of arrow
double arraow_len = Math.sqrt(L * L + H * H); // the length of arrow
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 x_3 = ex - arrXY_1[0]; // (x3,y3) the first point
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4) the second point
double y_4 = ey - 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();
// draw line
mCanvas.drawLine(sx, sy, ex, ey, mPaint);
Path triangle = new Path();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.close();
mCanvas.drawPath(triangle, mPaint);
}
// Calculate
public double[] rotateVec(int px, int 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;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
if (mAnnotation != null) {
float minX = 0;
float minY = 0;
float maxX = 0;
float maxY = 0;
switch (mAnnotation.getShape()) {
case Annotation.KEY_SHAPE_ARROW:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
case Annotation.KEY_SHAPE_SQUARES:
minX = getLeft() + mAnnotation.getRadius() / 2;
minY = getTop() + mAnnotation.getRadius() / 2;
maxX = getLeft() + getWidth() - mAnnotation.getRadius() / 2;
maxY = getTop() + getHeight() - mAnnotation.getRadius() / 2;
break;
case Annotation.KEY_SHAPE_CIRCLE:
minX = 0;
minY = 0;
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
case Annotation.KEY_SHAPE_TRIANGLE:
minX = getLeft() + mAnnotation.getRadius();
minY = getTop() + mAnnotation.getRadius();
maxX = getLeft() + getWidth() - mAnnotation.getRadius();
maxY = getTop() + getHeight() - mAnnotation.getRadius();
break;
}
if (x > minX && x < maxX && y > minY && y < maxY) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
case MotionEvent.ACTION_MOVE:
mAnnotation.setX(x);
mAnnotation.setY(y);
postInvalidate();
break;
}
}
return true;
}
return false;
}
public void startAnnotate(String pathName) {
mAnnotation = new Annotation();
mAnnotation.setMaxRadius(getWidth() / 2);
mAnnotation.setColor(Color.RED);
mAnnotation.setX(getWidth() / 2);
mAnnotation.setY(getHeight() / 2);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
annotations.add(mAnnotation);
postInvalidate();
}
public void stopAnnotate() {
if (annotations.isEmpty()) {
mPaint = null;
mAnnotation = null;
} else {
annotations.remove(annotations.size() - 1);
if (annotations.isEmpty()) {
mAnnotation = null;
mPaint = null;
} else {
mAnnotation = annotations.get(annotations.size() - 1);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(mAnnotation.getColor());
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(KEY_STROKE_WIDTH);
}
}
postInvalidate();
}
public void plus() {
if (mAnnotation != null) {
mAnnotation.plus();
postInvalidate();
}
}
public void sub() {
if (mAnnotation != null) {
mAnnotation.sub();
postInvalidate();
}
}
public void rotateRight() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() >= 360) {
mAnnotation.setDegree(0);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() + 90);
}
postInvalidate();
}
}
public void rotateLeft() {
if (mAnnotation != null) {
if (mAnnotation.getDegree() <= 0) {
mAnnotation.setDegree(270);
} else {
mAnnotation.setDegree(mAnnotation.getDegree() - 90);
}
postInvalidate();
}
}
public void changeColor(int color) {
if (mAnnotation != null) {
mAnnotation.setColor(color);
mPaint.setColor(color);
}
postInvalidate();
}
/**
* Change the shape
*
* @param id
*/
public void changeShape(int id) {
if (mAnnotation != null) {
mAnnotation.setShape(id);
postInvalidate();
}
}
/**
* Draw line
*
* @param fromX
* start point x
* @param fromY
* start point y
* @param toX
* end point x
* @param toY
* end point y
*/
public void drawLine(float fromX, float fromY, float toX, float toY) {
Path linePath = new Path();
linePath.moveTo(fromX, fromY);
linePath.lineTo(toX, toY);
linePath.close();
mCanvas.drawPath(linePath, mPaint);
invalidate();
}
public List<Annotation> getAnnotations() {
return annotations;
}
private void rotatePath(Path path, float degree) {
Matrix mMatrix = new Matrix();
RectF bounds = new RectF();
path.computeBounds(bounds, true);
mMatrix.postRotate(degree, (bounds.right + bounds.left) / 2, (bounds.bottom + bounds.top) / 2);
path.transform(mMatrix);
}
}
2. In your activity, create the AnnotationView and assign your image to it, then append this view to your root view.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AnnotationView mPreview = (FrameLayout) findViewById(R.id.camera_preview);
AnnotationView mAnnotationView = new AnnotationView(this);
Bitmap bitmap;
try {
bitmap = CBitmapUtil.decode(mPictureFile); // Get your image as a bitmap
mAnnotationView.setImageBitmap(bitmap);
mPreview.addView(mAnnotationView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
} catch (FileNotFoundException e) {
e.printStackTrace();
Toast.makeText(this, "Photo cannot be saved, please try again later.", Toast.LENGTH_SHORT).show();
}
}