3.自定义点类
顾名思义,就是为了获取点的相关的属性,其中基础属性图片左上角坐标与右下角坐标,计算图片中心位置以便获取图片中心点。状态标记,表示该点是否绘制到图片。下面是其实体类:
public class LYJGesturePoint {
private Point pointLeftTop;//左上角坐标
private Point pointRightBottom;//右下角坐标
private int centerX;//图片中心点X坐标
private int centerY;//图片中心点Y坐标
private int pointState;//是否点击了该图片
private int num;
public int getNum() {
return num;
}
public int getPointState() {
return pointState;
}
public void setPointState(int pointState) {
this.pointState = pointState;
}
public Point getPointLeftTop() {
return pointLeftTop;
}
public Point getPointRightBottom() {
return pointRightBottom;
}
public LYJGesturePoint(int left,int top,int right,int bottom,int i){
this.pointLeftTop=new Point(left,top);
this.pointRightBottom=new Point(right,bottom);
this.num=i;
}
public int getCenterX() {
this.centerX=(this.pointLeftTop.x+this.pointRightBottom.x)/2;
return centerX;
}
public int getCenterY() {
this.centerY=(this.pointLeftTop.y+this.pointRightBottom.y)/2;
return centerY;
}
}
4.自定义圆类
这个类较简单就三个属性而已(圆中心点坐标及半径),代码如下:
public class LYJCirclePoint {
private int roundX;//圆中心点X坐标
private int roundY;//圆中心点Y坐标
private int radiu;//圆半径
public int getRadiu() {
return radiu;
}
public int getRoundX() {
return roundX;
}
public int getRoundY() {
return roundY;
}
public LYJCirclePoint(int roundX,int roundY,int radiu){
this.roundX=roundX;
this.roundY=roundY;
this.radiu=radiu;
}
}
5.实现自定义绘制类View
代码如下:
public class LYJGestureView extends android.view.View {
/***
* 声明直线画笔
*/
private Paint paint;
/***
* 声明圆圈画笔
*/
private Paint circlePaint;
/***
* 画布
*/
private Canvas canvas;
/***
* 位图
*/
private Bitmap bitmap;
/***
* 装有各个view坐标的集合,用于判断点是否在其中
*/
private List<LYJGesturePoint> list;
/***
* 记录画过的线
*/
private List<Pair<LYJGesturePoint, LYJGesturePoint>> lineList;
/***
* 记录画过的圆
*/
private List<LYJCirclePoint> circlePoints;
/**
* 手指当前在哪个Point内
*/
private LYJGesturePoint currentPoint;
/***
* 手指按下动画
*/
private OnAnimationCallback animationCallback;
public interface OnAnimationCallback{
public void startAnimationImage(int i);
}
public void setAnimationCallback(OnAnimationCallback animationCallback) {
this.animationCallback = animationCallback;
}
public LYJGestureView(Context context, List<LYJGesturePoint> list){
super(context);
Log.i(getClass().getName(), "GestureDrawline");
paint = new Paint(Paint.DITHER_FLAG);// 创建一个画笔
circlePaint=new Paint(Paint.DITHER_FLAG);
DisplayMetrics metric = new DisplayMetrics();
((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(metric);
Log.i(getClass().getName(), "widthPixels" + metric.widthPixels);
Log.i(getClass().getName(), "heightPixels" + metric.heightPixels);
bitmap = Bitmap.createBitmap(metric.widthPixels, metric.heightPixels, Bitmap.Config.ARGB_8888); // 设置位图的宽高
canvas = new Canvas();
canvas.setBitmap(bitmap);
paint.setStyle(Paint.Style.STROKE);// 设置非填充
paint.setStrokeWidth(20);// 笔宽20像素
paint.setColor(Color.rgb(245, 142, 33));// 设置默认连线颜色
paint.setAntiAlias(true);// 不显示锯齿
circlePaint.setStyle(Paint.Style.FILL);
circlePaint.setStrokeWidth(1);
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.rgb(245, 142, 33));
this.list = list;
this.lineList = new ArrayList<>();
this.circlePoints=new ArrayList<>();
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
// 判断当前点击的位置是处于哪个点之内
currentPoint = getPointAt((int) event.getX(), (int) event.getY());
if (currentPoint != null) {
currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
this.animationCallback.startAnimationImage(currentPoint.getNum());
canvas.drawCircle(currentPoint.getCenterX(), currentPoint.getCenterY(), 20, circlePaint);
circlePoints.add(new LYJCirclePoint(currentPoint.getCenterX(),currentPoint.getCenterY(),20));
}
invalidate();
break;
case MotionEvent.ACTION_MOVE:
clearScreenAndDrawList();
// 得到当前移动位置是处于哪个点内
LYJGesturePoint pointAt = getPointAt((int) event.getX(), (int) event.getY());
if (currentPoint == null && pointAt == null) {//你把手指按在屏幕滑动,如果终点与起点都不图片那么返回
return true;
} else {// 代表用户的手指移动到了点上
if (currentPoint == null) {// 先判断当前的point是不是为null
// 如果为空,那么把手指移动到的点赋值给currentPoint
currentPoint = pointAt;
// 把currentPoint这个点设置选中状态;
currentPoint.setPointState(Constants.POINT_STATE_SELECTED);
}
}
//如果移动到的点不为图片区域或者移动到自己的地方,或者该图片已经为选中状态,直接画直线就可以了
if(pointAt == null || currentPoint.equals(pointAt) || Constants.POINT_STATE_SELECTED == pointAt.getPointState()){
canvas.drawCircle(currentPoint.getCenterX(), currentPoint.getCenterY(), 20, circlePaint);
circlePoints.add(new LYJCirclePoint(currentPoint.getCenterX(), currentPoint.getCenterY(), 20));
canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), event.getX(), event.getY(), paint);
}else{//其他情况画两点相连直线,并且保存绘制圆与直线,并调用按下图片的缩放动画
canvas.drawCircle(pointAt.getCenterX(),pointAt.getCenterY(),20,circlePaint);
circlePoints.add(new LYJCirclePoint(pointAt.getCenterX(), pointAt.getCenterY(), 20));
this.animationCallback.startAnimationImage(pointAt.getNum());
pointAt.setPointState(Constants.POINT_STATE_SELECTED);
canvas.drawLine(currentPoint.getCenterX(), currentPoint.getCenterY(), pointAt.getCenterX(), pointAt.getCenterY(), paint);
Pair<LYJGesturePoint, LYJGesturePoint> pair = new Pair<>(currentPoint, pointAt);
lineList.add(pair);
currentPoint=pointAt;//设置选中点为当前点。
}
invalidate();//重绘
break;
case MotionEvent.ACTION_UP:
clearScreenAndDrawList();//防止多出一条没有终点的直线
new Handler().postDelayed(new clearLineRunnable(), 1000);//1秒后清空绘制界面
invalidate();//重绘
break;
default:
break;
}
return true;
}
class clearLineRunnable implements Runnable {
public void run() {
// 清空保存点与圆的集合
lineList.clear();
circlePoints.clear();
// 重新绘制界面
clearScreenAndDrawList();
for (LYJGesturePoint p : list) {
//设置其为初始化不选中状态
p.setPointState(Constants.POINT_STATE_NORMAL);
}
invalidate();
}
}
/**
* 通过点的位置去集合里面查找这个点是包含在哪个Point里面的
*
* @param x
* @param y
* @return 如果没有找到,则返回null,代表用户当前移动的地方属于点与点之间
*/
private LYJGesturePoint getPointAt(int x, int y) {
for (LYJGesturePoint point : list) {
// 先判断点是否在图片的X坐标内
int leftX = point.getPointLeftTop().x;
int rightX = point.getPointRightBottom().x;
if (!(x >= leftX && x < rightX)) {
// 如果为假,则跳到下一个对比
continue;
}
//在判断点是否在图片的Y坐标内
int topY = point.getPointLeftTop().y;
int bottomY = point.getPointRightBottom().y;
if (!(y >= topY && y < bottomY)) {
// 如果为假,则跳到下一个对比
continue;
}
// 如果执行到这,那么说明当前点击的点的位置在遍历到点的位置这个地方
return point;
}
return null;
}
/**
* 清掉屏幕上所有的线,然后画出集合里面的线
*/
private void clearScreenAndDrawList() {
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
for (Pair<LYJGesturePoint, LYJGesturePoint> pair : lineList) {
canvas.drawLine(pair.first.getCenterX(), pair.first.getCenterY(),
pair.second.getCenterX(), pair.second.getCenterY(), paint);// 画线
}
for(LYJCirclePoint lyjCirclePoint : circlePoints){
canvas.drawCircle(lyjCirclePoint.getRoundX(),lyjCirclePoint.getRoundY(), lyjCirclePoint.getRadiu(),circlePaint);
}
}
//绘制用bitmap创建出来的画布
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
}










