先来看效果(效果不全,所有的点都可以动,圆的半径也可以变化)
直接来代码吧 (图片资源自己添加)复制即可看到效果
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathEffect;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
public class MyView extends View {
private int width;
private int height;
private ArrayList<int[]> list;
private Bitmap[] bitmaps;
private ArrayList<Integer> delyList;
//绘制背景图片
private Bitmap bitmap;
private Bitmap pic1;
private Bitmap pic2;
private Bitmap pic3;
private Bitmap pic4;
private Bitmap pic5;
private Bitmap pic6;
private Bitmap pic7;
public MyView(Context context) {
super(context);
init();
}
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
//绘制背景图片
bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.car_topview_full);
bitmaps = new Bitmap[]{
pic1 = BitmapFactory.decodeResource(getResources(), R.mipmap.pople),
pic2 = BitmapFactory.decodeResource(getResources(), R.mipmap.cirl),
pic3 = BitmapFactory.decodeResource(getResources(), R.mipmap.cirl),
pic4 = BitmapFactory.decodeResource(getResources(), R.mipmap.cirl),
pic5 = BitmapFactory.decodeResource(getResources(), R.mipmap.cirl),
pic6 = BitmapFactory.decodeResource(getResources(), R.mipmap.cirl),
pic7 = BitmapFactory.decodeResource(getResources(), R.mipmap.cirl)
};
list = new ArrayList();
/*int[] f1 = new int[]{getWidth() / 4 + 75, getHeight() / 8 + 75, getWidth() * 3 / 4 - 150 + 75, getHeight() / 8 + 75};
int[] f2 = new int[]{getWidth() / 4, getHeight() / 8, getWidth() / 4 + 150, getHeight() / 8 + 150};*/
int[] f1 = new int[]{500, 500};//中心
int[] f2 = new int[]{700, 700};
int[] f3 = new int[]{800, 800};
int[] f4 = new int[]{800, 800};
int[] f5 = new int[]{300, 300};
int[] f6 = new int[]{200, 200};
int[] f7 = new int[]{100, 100};
list.add(f1);
list.add(f2);
list.add(f3);
list.add(f4);
list.add(f5);
list.add(f6);
list.add(f7);
delyList = new ArrayList<>();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.BLACK);
Paint paint = new Paint();
Rect src = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
// 指定图片在屏幕上显示的区域
Rect dst = new Rect(getWidth() / 4, getHeight() / 8, getWidth() * 3 / 4, getHeight() * 7 / 8);
// 绘制图片
canvas.drawBitmap(bitmap, src, dst, null);
int maxRadus = calcCircleRadius(list);
//画虚线
calcPoint(canvas, paint, list, maxRadus);
//画点间的实线
paint.setColor(Color.RED);
paint.setStrokeWidth(10);
paint.setAntiAlias(true);
for (int i = 1; i < list.size(); i++) {
drawLie(canvas, paint, list.get(i));
}
//画各点的图
for (int i = 0; i < list.size(); i++) {
drawBitmap(canvas, list.get(i), bitmaps[i]);
}
//画文字
paint.setColor(Color.BLACK);
paint.setStrokeWidth(5);//设置画笔宽度
paint.setAntiAlias(true);//设置是否使用抗锯齿功能,如果使用,会导致绘图速度变慢
paint.setStyle(Paint.Style.FILL);//设置绘图样式,对于设置文字和几何图形都有效,可取值有三种 :1、Paint.Style.FILL:填充内部 2、Paint.Style.FILL_AND_STROKE:填充内部和描边 3、Paint.Style.STROKE:仅描边
paint.setTextAlign(Paint.Align.CENTER);//设置文字对齐方式
paint.setTextSize(50);//设置文字大小
for (int i = 1; i < delyList.size(); i++) {
drawText(canvas, paint, String.valueOf(maxRadus - delyList.get(i)), list.get(i));
}
// 虚线圆
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
//设置虚线
PathEffect dashPathEffect = new DashPathEffect(new float[]{5, 5}, 1);
paint.setPathEffect(dashPathEffect);
canvas.drawCircle(list.get(0)[0] + 75, list.get(0)[1] + 75, maxRadus, paint);
}
private void drawText(Canvas canvas, Paint paint, String text, int[] arr) {
canvas.drawText(text, arr[0] + 75, arr[1] + 100, paint);
/* if (arr[0] < getWidth() / 3) {
canvas.drawText("hello", arr[0]+75 , arr[1]+75, paint);
} else if (arr[0] > (getWidth() * 2 / 3)) {
canvas.drawText("hello", arr[0]+75 , arr[1]+75, paint);
} else {
}*/
}
/**
* 绘制实线延长线的虚线部分
*
* @param canvas
* @param paint
* @param list
* @param radius
*/
private void calcPoint(Canvas canvas, Paint paint, ArrayList<int[]> list, double radius) {
for (int i = 1; i < list.size(); i++) {
int x = (list.get(i)[0] + 75) - (list.get(0)[0] + 75);
int y = (list.get(i)[1] + 75) - (list.get(0)[1] + 75);
double radus = (int) Math.sqrt(x * x + y * y);
//计算半径和点到圆心距离的比例
double bili = radius / radus;
//根据比例就可以知道坐标的比例
//距离之间的比例就是坐标的比例
int endX = (int) ((list.get(0)[0] + 75) + x * bili);
int endY = (int) ((list.get(0)[1] + 75) + y * bili);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(10);
paint.setColor(Color.GRAY);
//设置虚线
PathEffect pathEffect = new DashPathEffect(new float[]{5, 5, 5, 5}, 1);
paint.setPathEffect(pathEffect);
Path path = new Path();
path.moveTo(list.get(0)[0] + 75, list.get(0)[1] + 75);
path.lineTo(endX, endY);
canvas.drawPath(path, paint);
//canvas.drawLine(list.get(0)[0] + 75, list.get(0)[1] + 75, endX, endY, paint);
}
}
/**
* 计算各点和中间点最大的距离,最大距离作为圆的半径
*
* @param list
* @return
*/
private int calcCircleRadius(ArrayList<int[]> list) {
int max = 0;
delyList.clear();
for (int i = 0; i < list.size(); i++) {
int x = list.get(0)[0] + 75 - (list.get(i)[0] + 75);
int y = list.get(0)[1] + 75 - (list.get(i)[1] + 75);
double radus = Math.sqrt(x * x + y * y);
delyList.add((int) radus);
if (radus > max) {
max = (int) radus;
}
}
return max;
}
private void drawLie(Canvas canvas, Paint paint, int[] arr) {
canvas.drawLine(list.get(0)[0] + 75, list.get(0)[1] + 75, arr[0] + 75, arr[1] + 75, paint);
}
private void drawBitmap(Canvas canvas, int[] arr, Bitmap pic) {
Rect src1 = new Rect(0, 0, pic.getWidth(), pic.getHeight());
Rect dst1 = new Rect(arr[0], arr[1], arr[0] + 150, arr[1] + 150);
canvas.drawBitmap(pic, src1, dst1, null);
}
float downX = 0;
float downY = 0;
//当前拖动的实那个按钮,没有选中状态为-1
int current = -1;
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
for (int i = 0; i < list.size(); i++) {
int[] arr = list.get(i);
if (downX > arr[0] && downX < arr[0] + 150 && downY > arr[1] && downY < arr[1] + 150) {
Log.e("MyView", "第" + i + "个 " + downX + " _ " + downY);
current = i;
break;
}
}
break;
case MotionEvent.ACTION_MOVE:
if (current != -1) {
if (event.getX() < (getWidth() / 4 + 75)) {
list.get(current)[0] = getWidth() / 4;
} else if (event.getX() > (getWidth() * 3 / 4 - 75)) {
list.get(current)[0] = getWidth() * 3 / 4 - 150;
} else {
list.get(current)[0] = (int) event.getX() - 75;
}
if (event.getY() < (getHeight() / 4)) {
list.get(current)[1] = getHeight() / 4 - 75;
} else if (event.getY() > (getHeight() * 3 / 4)) {
list.get(current)[1] = getHeight() * 3 / 4 - 75;
} else {
list.get(current)[1] = (int) event.getY() - 75;
}
//list.get(current)[0] = (int) event.getX() - 75;
//list.get(current)[1] = (int) event.getY() - 75;
invalidate();
}
break;
case MotionEvent.ACTION_UP:
current = -1;
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}