小动画之“绘画板”(二阶贝塞尔曲线)
二阶贝塞尔曲线实现绘画板效果
- 1. 什么是二阶贝塞尔曲线
- 2. 曲线函数 quadTo()
- 3. 原理分析
- 4. 代码实现
- 4.1 自定义控件
- 4.2 重写 OnTouchEvent() 函数
- 4.3 重写 onDraw() 方法
- 4.4 注意
- 5. rQuadTo() 函数

如左图,使用一阶贝塞尔曲线绘制,图线不光滑,会有明显折线效果;
如右图,使用二阶贝塞尔曲线,图线光滑圆润。
1. 什么是二阶贝塞尔曲线

2. 曲线函数 quadTo()
-
函数
//二阶贝济埃曲线 public void quadTo(float xl , float yl, float x2 , float y2); -
参数
(xl , y1) 是控制点 P1 坐标,(x2,y2)是终点 P2 坐标。
起始点 P0 是通过 Path.moveTo(x,y)函数来指定的;
如果连续调用quadTo() 函数,那么前一个 quadTo() 函数的终点就是下一个 quadTo() 函数的起始点。
3. 原理分析
-
捕捉手势轨迹
在自定义控件中拦截 OnTouchEvent,根据手指的移动轨迹来绘制 Path;
-
实现方法:
最简单的方法就是直接调用 Path.lineTo() 函数把各个点连接起来。
效果如首图左侧所示,存在明显的折线效果。
4. 代码实现
4.1 自定义控件
-
在构造函数中初始化相关的参数;
public class NormalGestureTrackView extends View {private Paint mPaint;private Path mPath;//起始点坐标private float mPreX;private float mPreY;//结束点坐标private float mEndX;private float mEndY;public NormalGestureTrackView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(Color.RED);mPaint.setStrokeWidth(5);mPaint.setStyle(Paint.Style.STROKE);mPath = new Path();}@Overridepublic boolean onTouchEvent(MotionEvent event) {……return super.onTouchEvent(event);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawPath(mPath, mPaint);} }
4.2 重写 OnTouchEvent() 函数
- 调用 Path 的 moveTo() 和 lineTo() 函数将手势经过的点连接起来。
@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:mPreX = event.getX();mPreY = event.getY();mPath.moveTo(mPreX, mPreY);return true;case MotionEvent.ACTION_MOVE:if (GestureTrackActivity.isLineTo) {mEndX = event.getX();mEndY = event.getY();mPath.lineTo(mEndX, mEndY);} else {mEndX = (event.getX() + mPreX) / 2;mEndY = (event.getY() + mPreY) / 2;mPath.quadTo(mPreX, mPreY, mEndX, mEndY);mPreX = event.getX();mPreY = event.getY();}invalidate();break;default:break;}return super.onTouchEvent(event);}
-
注意:
这里我在调用该 View 的 activity 中定义了静态布尔值常量 isLineTo ,默认为 true,默认使用 lineTo() 连接,当点击 btn 时取反;
当 isLineTo 为 true 时,使用一个方法,为 false 时,使用二阶贝塞尔曲线;
-
关于 EndX 取值,请参考如图理解;

4.3 重写 onDraw() 方法
-
画出轨迹
@Override protected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawPath(mPath, mPaint); }
4.4 注意
-
在 MotionEvent.ACTION_DOWN 中 返回 true;并且没有 break;表示当前控件已经消费了下按动作,之后的ACTION_MOVE 、ACTION_UP 动作也会继续传递到当前/控件中:
-
重绘控件使用的是 postlnvalidate() 函数,也可以使用 Inval idate() 函数。这两个函数都可以重绘控件,
区别是 Invalidate() 函数一定要在主线程中执行, 否则会报错
postlnvalidate() 函数可以在任何线程中执行;
5. rQuadTo() 函数
publiC void rQuadTo(float dxl , float dyl, float dx2, float dy2)
具体实现与详解,请看:小动画之"波浪动画";
声明:本文整理自《《Android自定义控件开发入门与实战》_启舰》;
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
