先看效果图
如效果图所示主要包括四个自定义View:挖掘机工作装置姿态、车体的左右和前后倾角、车身的回转角度、随车吊。
其中挖掘机工作装置的姿态已经在以前的文章中介绍过。
前后左右倾角控件主要涉及到圆弧角度的转换和圆弧的绘图方法,车体法线的角度变换,前后的倾角分别用浅绿色和浅蓝色区域标识,浅绿色区域越多表示车体后倾角度越大。法线左右偏移越大表示左右倾斜越大。主要涉及到的知识点是画笔Paint、Matrix、Path、DashPathEffect、drawArc、drawText的使用。
回转角度的控件,主要是中间类似车体的图片描绘,看似是矩形,其实利用设置画笔的setStrokeWidth()进行画线操作。
前后左右倾角控件和回转角度的控件十分类似。
随车吊控件主要确定如图所示的关键点
从左到右依次是吊臂轴心旋转点,吊臂第一节结束点,吊臂第二节结束点,吊臂第二节预留长度点,吊臂末端结束点,最下面一点是与挂钩连接的点。
吊臂的旋转与伸缩都是通过对以上几个点的Matrix的旋转和平移变换得到,最后进行drawLine。吊钩的位置通过计算与挂钩连接点的距离确定。
前后左右倾角控件关键代码
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画外框的⚪
mPaint.setStyle(Paint.Style.STROKE);
DashPathEffect effects1 = new DashPathEffect(new float[] { 2, 2}, 1);
mPaint.setPathEffect(effects1);
canvas.drawCircle(centerXY,centerXY,radiusOutSide,mPaint);
//画水平线
Path horLinePath = new Path();
horLinePath.moveTo(pointStart[0],pointStart[1]);
horLinePath.lineTo(pointEnd[0],pointEnd[1]);
canvas.drawPath(horLinePath , horLinePaint);
//画左右倾斜线
lineMatrix.reset();
//计算旋转角度
lineMatrix.setRotate(calLRAngle(lrSlope),centerXY,centerXY);
lineMatrix.mapPoints(pointSpinStart,pointStart);
lineMatrix.mapPoints(pointSpinEnd,pointEnd);
canvas.drawLine(pointSpinStart[0],pointSpinStart[1],pointSpinEnd[0],pointSpinEnd[1],paintLR);
paintLR.setStyle(Paint.Style.FILL);
canvas.drawCircle(pointSpinStart[0],pointSpinStart[1],5,paintLR);
Path verLinePath = new Path();
verLinePath.moveTo(centerXY,centerXY);
verLinePath.lineTo(pointSpinStart[0],pointSpinStart[1]);
canvas.drawPath(verLinePath , verLinePaint);
Path verLinePath1 = new Path();
verLinePath1.moveTo(centerXY,centerXY);
verLinePath1.lineTo(pointSpinEnd[0],pointSpinEnd[1]);
canvas.drawPath(verLinePath1 , verLinePaint);
//画前后倾角
FBShopePara fbShopePara = calFBAngle(fbSlope);
canvas.drawArc(rectFOval,fbShopePara.fStartAngle+lrSlope,fbShopePara.fSweepAngle,false,paintFOval);
canvas.drawArc(rectFOval,fbShopePara.bStartAngle+lrSlope,fbShopePara.bSweepAngle,false,paintBOval);
//画圆心
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerXY,centerXY,3,mPaint);
//画text
drawText(canvas);
// changeLRAngle();
// changeFBAngle();
// invalidate();
}
//计算左右角度
private float calLRAngle(float lrSlope){
//private double lrSlope;//左右的倾角 -90.0~90.0度
//左是负数 右边是正数
//转换成绕圆形旋转的度数
return (float) (90.0+lrSlope);
}
//计算前后角度
private FBShopePara calFBAngle(float fbSlope){
FBShopePara para = new FBShopePara();
//fbSlope = fbSlope*2;//-90+90
//前倾负数的角度
//后倾是正的角度
para.fStartAngle = -(180+fbSlope);
para.fSweepAngle = (180+2*fbSlope);
para.bStartAngle = fbSlope;
para.bSweepAngle = 180-2*fbSlope;
return para;
}
class FBShopePara{
float fStartAngle;
float fSweepAngle;
float bStartAngle;
float bSweepAngle;
}
回转角度控件关键代码
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//画外框的⚪
int strokeWidth = SizeUtils.dp2px(3);
paintCircle.setStrokeWidth(strokeWidth);
paintCircle.setStyle(Paint.Style.STROKE);
DashPathEffect effects1 = new DashPathEffect(new float[] { 2, 2}, 1);
paintCircle.setPathEffect(effects1);
canvas.drawCircle(centerXY,centerXY,radiusOutSide,paintCircle);
//画水平和竖直线
paintCircle.setStrokeWidth(1);
canvas.drawLine(
pointStart[0],
pointStart[1],
pointEnd[0],
pointEnd[1],
paintCircle
);
canvas.drawLine(
pointSpinStart[0],
pointSpinStart[1],
pointSpinEnd[0],
pointSpinEnd[1],
paintCircle
);
rotateMatrix.reset();
rotateMatrix.setRotate(slewAngle,centerXY,centerXY);
rotateMatrix.mapPoints(pointSpinBoom1End,pointBoom1End);
rotateMatrix.mapPoints(pointSpinBoom2End,pointBoom2End);
rotateMatrix.mapPoints(pointSpinCabStart,pointCabStart);
rotateMatrix.mapPoints(pointSpinCabEnd,pointCabEnd);
rotateMatrix.mapPoints(pointSpinEqueStart,pointEqueStart);
rotateMatrix.mapPoints(pointSpinEqueEnd,pointEqueEnd);
rotateMatrix.mapPoints(pointSpinBackStart,pointBackStart);
rotateMatrix.mapPoints(pointSpinBackEnd,pointBackEnd);
//画动臂
paintYellow.setStrokeWidth(SizeUtils.dp2px(10));
canvas.drawLine(centerXY,centerXY,pointSpinBoom1End[0],pointSpinBoom1End[1],paintYellow);
paintBlack.setStrokeWidth(SizeUtils.dp2px(10));
canvas.drawLine(pointSpinBoom1End[0],pointSpinBoom1End[1],pointSpinBoom2End[0],pointSpinBoom2End[1],paintBlack);
//画驾驶室
paintBlack.setStrokeWidth(SizeUtils.dp2px(15));
canvas.drawLine(pointSpinCabStart[0],pointSpinCabStart[1],pointSpinCabEnd[0],pointSpinCabEnd[1],paintBlack);
//画工作装置根区域
canvas.drawLine(pointSpinEqueStart[0],pointSpinEqueStart[1],pointSpinEqueEnd[0],pointSpinEqueEnd[1],paintYellow);
//画配重区域
paintYellow.setStrokeWidth(SizeUtils.dp2px(25));
canvas.drawLine(pointSpinBackStart[0],pointSpinBackStart[1],pointSpinBackEnd[0],pointSpinBackEnd[1],paintYellow);
//画圆心
paintCircle.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerXY,centerXY,3,paintCircle);
//书写角度
drawText(canvas);
// changeAngle();
// invalidate();
}
随车吊控件关键代码
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLUE);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
//canvas.drawRect(new Rect(0,0,SizeUtils.dp2px(320),SizeUtils.dp2px(320)),paint);
//画吊臂
paintYellow.setStrokeWidth(SizeUtils.dp2px(22));
canvas.drawLine(centerXo,centerYo,pointSpin1[0],pointSpin1[1],paintYellow);
paintBlack.setStrokeWidth(SizeUtils.dp2px(18));
canvas.drawLine(pointSpin1[0],pointSpin1[1],pointSpin3[0],pointSpin3[1],paintBlack);
paintBlack.setStrokeWidth(SizeUtils.dp2px(26));
canvas.drawLine(pointSpin3[0],pointSpin3[1],pointSpin4[0],pointSpin4[1],paintBlack);
//画车体
canvas.drawBitmap(bitmapBody,rectBody,rectFBody,paintBody);
//画吊绳
paintBlackLine.setStrokeWidth(SizeUtils.dp2px(1));
canvas.drawLine(pointSpin5[0],pointSpin5[1],pointSpin5[0],rectFHook.top,paintBlackLine);
//画吊钩
canvas.drawBitmap(bitmapHook,rectHook,rectFHook,paintBody);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setColor(Color.RED);
//旋转的轴心选择,尝试的两个点
// canvas.drawCircle(centerX,centerY,5,paint);
// canvas.drawCircle(centerX,centerY-SizeUtils.dp2px(20),5,paint);
//画关键点
canvas.drawCircle(centerX+SizeUtils.dp2px(20),centerY-SizeUtils.dp2px(20),5,paint);
canvas.drawCircle(pointSpin1[0],pointSpin1[1],5,paint);
canvas.drawCircle(pointSpin2[0],pointSpin2[1],5,paint);
canvas.drawCircle(pointSpin3[0],pointSpin3[1],5,paint);
canvas.drawCircle(pointSpin4[0],pointSpin4[1],5,paint);
canvas.drawCircle(pointSpin5[0],pointSpin5[1],5,paint);
}
public void setPara(float angleCrane,float lengthCrane,float heightCrane){
Matrix matrix = new Matrix();
//先平移
matrix.preTranslate((lengthCrane-100)*SizeUtils.dp2px(100)/100,0);
//再旋转
matrix.postRotate(0-angleCrane,centerXo,centerYo);
matrix.mapPoints(pointSpin2,point2);
matrix.mapPoints(pointSpin3,point3);
matrix.mapPoints(pointSpin4,point4);
matrix.mapPoints(pointSpin5,point5);
matrix.reset();
matrix.setRotate(0-angleCrane,centerXo,centerYo);
matrix.mapPoints(pointSpin1,point1);
//钩子的位置
//目前的最长距离
float distance = point5[1]-pointSpin5[1];
//100最上面
//0最下面
float distanceY = pointSpin5[1]+(100-heightCrane)*distance/100;
rectFHook = rectFHook = new RectF(
pointSpin5[0]- SizeUtils.dp2px(10.5f),
distanceY,
pointSpin5[0]+ SizeUtils.dp2px(10.5f),
distanceY+ SizeUtils.dp2px(33f)
);
invalidate();
}