直播页面8:自定义View贝塞尔曲线
一.绘制一阶
public class BezierView extends View {
private Path mPath;//路径
private Paint mPaint;//画笔
//java代码
public BezierView(Context context) {
super(context);
initPaint();
}
//xml布局
public BezierView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void initPaint() {
//画笔
mPaint = new Paint();
//设置样式 STROKE:空心 FILL:实心
mPaint.setStyle(Paint.Style.STROKE);
//设置宽度
mPaint.setStrokeWidth(20);
//抗锯齿
mPaint.setAntiAlias(true);
//防抖动
mPaint.setDither(true);
//路径
mPath = new Path();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制一阶曲线
drawOneBezier(canvas);
}
//绘制一阶曲线
private void drawOneBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,50);
//路径终点
mPath.lineTo(100,150);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
}
}
二.绘制二阶和三阶
1.二阶: mPath.quadTo(twoControlX,twoControlY,100,150);
2.三阶:mPath.cubicTo(threeControlX1,threeControlY1, threeControlX2, threeControlY2, 500, 500);
public class BezierView extends View {
private Path mPath;//路径
private Paint mPaint;//画笔
//二阶曲线的控制点
public float twoControlX = 50;
public float twoControlY = 50;
//三阶曲线的控制点
public float threeControlX1 = 200;
public float threeControlY1 = 300;
public float threeControlX2 = 400;
public float threeControlY2 = 300;
//java代码
public BezierView(Context context) {
super(context);
initPaint();
}
//xml布局
public BezierView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void initPaint() {
//画笔
mPaint = new Paint();
//设置样式 STROKE:空心 FILL:实心
mPaint.setStyle(Paint.Style.STROKE);
//设置宽度
mPaint.setStrokeWidth(20);
//抗锯齿
mPaint.setAntiAlias(true);
//防抖动
mPaint.setDither(true);
//路径
mPath = new Path();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制一阶曲线
drawOneBezier(canvas);
//绘制二阶曲线
drawTwoBezier(canvas);
//绘制三阶曲线
drawThreeBezier(canvas);
}
//绘制三阶曲线
private void drawThreeBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,250);
//绘制3阶
mPath.cubicTo(threeControlX1,threeControlY1, threeControlX2, threeControlY2, 500, 500);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
}
//绘制二阶曲线
private void drawTwoBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,250);
//绘制2阶 1:控制点X 2:控制点Y 3:终点X 4:终点的Y
mPath.quadTo(twoControlX,twoControlY,100,150);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
}
//绘制一阶曲线
private void drawOneBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,50);
//路径终点
mPath.lineTo(100,150);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
}
}
三.绘制辅助线和控制点
//绘制二阶曲线
private void drawTwoBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,250);
//绘制2阶 1:控制点X 2:控制点Y 3:终点X 4:终点的Y
mPath.quadTo(twoControlX,twoControlY,500,250);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
//---辅助线---
//设置画笔的颜色
mPaint.setColor(Color.YELLOW);
//通过path对象移动到起点位置
mPath.moveTo(50, 250);
//画一个从起点到控制点的线
mPath.lineTo( twoControlX, twoControlY);
//从控制点到终点的线
mPath.lineTo(500, 250);
//绘制路径
canvas.drawPath(mPath, mPaint);
//重置路径
mPath.reset();
//---画出控制的点---
//设置画笔的颜色
mPaint.setColor(Color.GREEN);
//画一个控制点的圆 圆心是控制点的X和Y 半径是10
canvas.drawCircle( twoControlX, twoControlY, 10, mPaint);
//重置路径
mPath.reset();
}
//绘制三阶曲线
private void drawThreeBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,500);
//绘制3阶
mPath.cubicTo(threeControlX1,threeControlY1, threeControlX2, threeControlY2, 500, 500);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
//---辅助线---
mPaint.setColor(Color.YELLOW);
//通过path对象移动到起点位置
mPath.moveTo(50, 500);
//从起点画到第一个控制点
mPath.lineTo( threeControlX1, threeControlY1);
//从第一个控制点画到第二个控制点
mPath.lineTo( threeControlX2, threeControlY2);
//从第二个控制点画到终点
mPath.lineTo(500, 500);
//绘制路径
canvas.drawPath(mPath, mPaint);
//重置路径
mPath.reset();
//---画出控制的点---
mPaint.setColor(Color.GREEN);
//画二个控制点的圆 圆心是控制点的X和Y 半径是10
canvas.drawCircle( threeControlX1, threeControlY1, 10, mPaint);
canvas.drawCircle( threeControlX2, threeControlY2, 10, mPaint);
}
四.勾股定理:碰撞测试
1.碰撞测试
//判断手指的触点是否在圆内,碰撞判断
private boolean isChekCircle(PointF pointF, PointF circle, float radius) {
return Math.pow((pointF.x - circle.x),2)+Math.pow((pointF.y-circle.y),2)<= Math.pow(radius,2);
}
2.事件处理
//消费后做处理 getAction Down Move Up
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//当手指按下得时候
case MotionEvent.ACTION_DOWN:
//判断二阶得点有没有被点击到
boolean twoControl = isChekCircle(new PointF(event.getX(), event.getY()),
new PointF((float) twoControlX, (float) twoControlY), 50);
//判断三阶得点有没有被点击到
boolean threeControl1 = isChekCircle(new PointF(event.getX(), event.getY()),
new PointF((float) threeControlX1, (float) threeControlY1), 50);
boolean threeControl2 = isChekCircle(new PointF(event.getX(), event.getY()),
new PointF((float) threeControlX2, (float) threeControlY2), 50);
if (twoControl) {
mType = 0;
} else if (threeControl1) {
mType = 1;
} else if (threeControl2) {
mType = 2;
} else {
mType = -1;
}
break;
//当手指移动得时候
case MotionEvent.ACTION_MOVE:
//将当前得点赋值给二阶贝塞尔曲线得控制点
if (mType == 0) {
twoControlX = event.getX();
twoControlY = event.getY();
invalidate();
//将当前得点赋值给三阶贝塞尔曲线得控制点1
} else if (mType == 1) {
threeControlX1 = event.getX();
threeControlY1 = event.getY();
invalidate();
// 将当前得点赋值给三阶贝塞尔曲线得控制点2
} else if (mType == 2) {
threeControlX2 = event.getX();
threeControlY2 = event.getY();
invalidate();
}
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
3.全部代码
public class BezierView extends View {
private Path mPath;//路径
private Paint mPaint;//画笔
//二阶曲线的控制点
public float twoControlX = 50;
public float twoControlY = 50;
//三阶曲线的控制点
public float threeControlX1 = 200;
public float threeControlY1 = 300;
public float threeControlX2 = 400;
public float threeControlY2 = 300;
//判断碰撞
private int mType;
//java代码
public BezierView(Context context) {
super(context);
initPaint();
}
//xml布局
public BezierView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public BezierView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void initPaint() {
//画笔
mPaint = new Paint();
//设置样式 STROKE:空心 FILL:实心
mPaint.setStyle(Paint.Style.STROKE);
//设置宽度
mPaint.setStrokeWidth(20);
//抗锯齿
mPaint.setAntiAlias(true);
//防抖动
mPaint.setDither(true);
//路径
mPath = new Path();
}
//测量View的大小
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//单独测量宽高
int w = measureSingle(widthMeasureSpec);
int h = measureSingle(heightMeasureSpec);
//设置宽高
setMeasuredDimension(w, h);
}
//单独测量
private int measureSingle(int measureSpec) {
int result = 0;
//测量模式
int mode = MeasureSpec.getMode(measureSpec);
//测量大小
int size = MeasureSpec.getSize(measureSpec);
//当是无限模式 返回200
if (mode == MeasureSpec.AT_MOST) {//当WRAP
result = 500;
} else {
result = size;
}
return result;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制一阶曲线
drawOneBezier(canvas);
//绘制二阶曲线
drawTwoBezier(canvas);
//绘制三阶曲线
drawThreeBezier(canvas);
}
//绘制三阶曲线
private void drawThreeBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,500);
//绘制3阶
mPath.cubicTo(threeControlX1,threeControlY1, threeControlX2, threeControlY2, 500, 500);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
//---辅助线---
mPaint.setColor(Color.YELLOW);
//通过path对象移动到起点位置
mPath.moveTo(50, 500);
//从起点画到第一个控制点
mPath.lineTo( threeControlX1, threeControlY1);
//从第一个控制点画到第二个控制点
mPath.lineTo( threeControlX2, threeControlY2);
//从第二个控制点画到终点
mPath.lineTo(500, 500);
//绘制路径
canvas.drawPath(mPath, mPaint);
//重置路径
mPath.reset();
//---画出控制的点---
mPaint.setColor(Color.GREEN);
//画二个控制点的圆 圆心是控制点的X和Y 半径是10
canvas.drawCircle( threeControlX1, threeControlY1, 10, mPaint);
canvas.drawCircle( threeControlX2, threeControlY2, 10, mPaint);
}
//绘制二阶曲线
private void drawTwoBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,250);
//绘制2阶 1:控制点X 2:控制点Y 3:终点X 4:终点的Y
mPath.quadTo(twoControlX,twoControlY,500,250);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
//---辅助线---
//设置画笔的颜色
mPaint.setColor(Color.YELLOW);
//通过path对象移动到起点位置
mPath.moveTo(50, 250);
//画一个从起点到控制点的线
mPath.lineTo( twoControlX, twoControlY);
//从控制点到终点的线
mPath.lineTo(500, 250);
//绘制路径
canvas.drawPath(mPath, mPaint);
//重置路径
mPath.reset();
//---画出控制的点---
//设置画笔的颜色
mPaint.setColor(Color.GREEN);
//画一个控制点的圆 圆心是控制点的X和Y 半径是10
canvas.drawCircle( twoControlX, twoControlY, 10, mPaint);
//重置路径
mPath.reset();
}
//绘制一阶曲线
private void drawOneBezier(Canvas canvas) {
//设置画笔颜色
mPaint.setColor(Color.RED);
//路径起点
mPath.moveTo(50,50);
//路径终点
mPath.lineTo(100,150);
//绘制路径
canvas.drawPath(mPath,mPaint);
//重置路径
mPath.reset();
}
//生成一个事务
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
return super.dispatchTouchEvent(event);
}
//消费后做处理 getAction Down Move Up
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
//当手指按下得时候
case MotionEvent.ACTION_DOWN:
//判断二阶得点有没有被点击到
boolean twoControl = isChekCircle(new PointF(event.getX(), event.getY()),
new PointF((float) twoControlX, (float) twoControlY), 50);
//判断三阶得点有没有被点击到
boolean threeControl1 = isChekCircle(new PointF(event.getX(), event.getY()),
new PointF((float) threeControlX1, (float) threeControlY1), 50);
boolean threeControl2 = isChekCircle(new PointF(event.getX(), event.getY()),
new PointF((float) threeControlX2, (float) threeControlY2), 50);
if (twoControl) {
mType = 0;
} else if (threeControl1) {
mType = 1;
} else if (threeControl2) {
mType = 2;
} else {
mType = -1;
}
break;
//当手指移动得时候
case MotionEvent.ACTION_MOVE:
//将当前得点赋值给二阶贝塞尔曲线得控制点
if (mType == 0) {
twoControlX = event.getX();
twoControlY = event.getY();
invalidate();
//将当前得点赋值给三阶贝塞尔曲线得控制点1
} else if (mType == 1) {
threeControlX1 = event.getX();
threeControlY1 = event.getY();
invalidate();
// 将当前得点赋值给三阶贝塞尔曲线得控制点2
} else if (mType == 2) {
threeControlX2 = event.getX();
threeControlY2 = event.getY();
invalidate();
}
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
//判断手指的触点是否在圆内,碰撞判断
private boolean isChekCircle(PointF pointF, PointF circle, float radius) {
return Math.sqrt(Math.pow((pointF.x - circle.x), 2) + Math.pow((pointF.y - circle.y), 2)) <= radius;
}
}