Android自定义View之使用Path绘制手势轨迹和水波效果
来源:互联网 发布:mac程序文件夹在哪里 编辑:程序博客网 时间:2024/06/05 01:58
先看下效果图:
绘制轨迹
绘制手指的轨迹主要是拦截View的onTouchEvent()方法,并根据手指的轨迹绘制path。path中有两种可以实现的方法
1、Path.lineTo(x,y)方法
public class MovePathView extends View { private Path mPath; private Paint mPaint; //手指按下的位置 private float startX,startY; public MovePathView(Context context) { super(context); init(); } //初始化 private void init() { mPaint = new Paint(); mPath = new Path(); mPaint.setColor(Color.BLUE); mPaint.setAntiAlias(true); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(4); } public MovePathView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MovePathView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: startX = event.getX(); startY = event.getY(); //设置原点 mPath.moveTo(startX,startY); break; case MotionEvent.ACTION_UP: break; case MotionEvent.ACTION_MOVE: float currX = event.getX(); float currY = event.getY(); //连线 mPath.lineTo(currX,currY); //刷新view invalidate(); break; } //返回true,消费事件 return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPath(mPath,mPaint); } //对外提供的方法,重新绘制 public void reset(){ mPath.reset(); invalidate(); }}
这里面需要知道的应该就3个点:
- View的坐标系
- View的事件分发
- Path的moveTo(),lineTo()方法
2、使用Path.quadTo()绘制曲线
public class MoveQuatoView extends View { private Paint mPaint; private Path mPath; //上个位置 private float mPreX,mPreY; //结束位置 private float endY,endX; public MoveQuatoView(Context context) { super(context); init(); } public MoveQuatoView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public MoveQuatoView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //初始化 private void init() { mPath = new Path(); mPaint = new Paint(); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(5); mPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawPath(mPath,mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: mPath.moveTo(event.getX(), event.getY()); mPreX = event.getX(); mPreY = event.getY(); break; case MotionEvent.ACTION_MOVE: endX = (mPreX + event.getX()) / 2; endY = (mPreY + event.getY()) / 2; mPath.quadTo(mPreX, mPreY, endX, endY); mPreX = event.getX(); mPreY = event.getY(); invalidate(); break; } return true; }}
上面一段代码为了取得平滑的效果,所以endX和endY都只取了直线的中间部分。
水波纹效果
水波纹主要用到了Path.rQuadTo()
方法。
rQuadTo()也是绘制曲线的一个方法。
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Paint paint = new Paint(); paint.setColor(Color.RED); paint.setStrokeWidth(5); paint.setStyle(Paint.Style.STROKE); paint.setAntiAlias(true); Path path = new Path(); path.moveTo(100,300); /** rQuadTo(float dx1, float dy1, float dx2, float dy2) dx1:控制点X坐标,表示相对上一个终点X坐标的位移坐标,可为负值,正值表示相加,负值表示相减; dy1:控制点Y坐标,相对上一个终点Y坐标的位移坐标。同样可为负值,正值表示相加,负值表示相减; dx2:终点X坐标,同样是一个相对坐标,相对上一个终点X坐标的位移值,可为负值,正值表示相加,负值表示相减; dy2:终点Y坐标,同样是一个相对,相对上一个终点Y坐标的位移值。可为负值,正值表示相加,负值表示相减; */ path.rQuadTo(100,-100,200,0); path.rQuadTo(100,100,200,0); canvas.drawPath(path,paint); }
上面代码总共有两个rQuadTo()方法。
第一个path.rQuadTo(100,-100,200,0);
path.rQuadTo(100,100,200,0);`
起始点:(100,300)
控制点坐标:(200,200),X:200=100+100,Y: 200 = 300-100
终点坐标: (300,300), X :300=100+200,Y:300 = 300+0
效果是:![image2.png](http://upload-images.jianshu.io/upload_images/2729169-8a82e6e36cd5cf8b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
第二个
此时的起始点坐标也就是第一个的终点坐标,所以
起始点坐标:(300,300)
控制点坐标:(400,400),X: 400 = 300+100,Y:400 = 300+100
终点坐标: (500,300),X: 500 = 300+200,Y:300 = 300+0
同理,如果有第三个path.rQuadTo,那么第三个的起始点也就是上一个的终点(500,300)
搞清楚了path.rQuadTo()
方法的用法就可以去实现水波纹的效果了。
public class RippleView extends View { private Paint mPaint; private Path mPath; //波纹的宽度 private int mItemWaveLength = 1000; //波纹每次移动的距离 private int dx; public RippleView(Context context) { super(context); init(); } public RippleView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RippleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //初始化 private void init(){ mPath = new Path(); mPaint = new Paint(); mPaint.setColor(Color.RED); mPaint.setStyle(Paint.Style.FILL_AND_STROKE); mPaint.setStrokeWidth(5); mPaint.setAntiAlias(true); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //移动后,重置mPath,将之前路径清空 mPath.reset(); //距离顶部的高度 int originY = 600; //波纹宽度的一般 int halfWaveLen = mItemWaveLength/2; //随着刷新,每次移动dx距离 mPath.moveTo(-mItemWaveLength+dx,originY); //for循环当前屏幕中所有的波纹 for (int i = -mItemWaveLength;i<=getWidth()+mItemWaveLength;i+=mItemWaveLength){ mPath.rQuadTo(halfWaveLen/2,-100,halfWaveLen,0); mPath.rQuadTo(halfWaveLen/2,100,halfWaveLen,0); } mPath.lineTo(getWidth(),getHeight()); mPath.lineTo(0,getHeight()); mPath.close(); canvas.drawPath(mPath,mPaint); } /** * 动画的目的是让波纹移动起来 * 利用调用在path.moveTo的时候,将起始点向右移动即可实现移动, * 而且只要我们移动一个波长的长度,波纹就会重合,就可以实现无限循环了 */ public void startAnim(){ //动画移动的距离 0~mItemWaveLength ValueAnimator animator = ValueAnimator.ofInt(0,mItemWaveLength); //时间 animator.setDuration(2000); //重复次数,这里是无限次 animator.setRepeatCount(ValueAnimator.INFINITE); animator.setInterpolator(new LinearInterpolator()); //动画刷新监听 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //每次移动的距离 dx = (int)animation.getAnimatedValue(); //刷新View postInvalidate(); } }); animator.start(); }}
这样就实现了一个水波纹的效果了。
本文参考:
自定义控件三部曲之绘图篇(六)——Path之贝赛尔曲线和手势轨迹、水波纹效果
- Android自定义View之使用Path绘制手势轨迹和水波效果
- Android自定义控件-Path之贝赛尔曲线和手势轨迹、水波纹效果
- 自定义控件之绘图篇:Path之贝赛尔曲线和手势轨迹、水波纹效果
- 自定义控件三部曲之绘图篇(六)——Path之贝赛尔曲线和手势轨迹、水波纹效果
- 自定义控件三部曲之绘图篇(六)——Path之贝赛尔曲线和手势轨迹、水波纹效果
- 自定义控件三部曲之绘图篇(六)——Path之贝赛尔曲线和手势轨迹、水波纹效果
- 自定义控件之绘图篇(六) —— Path之贝赛尔曲线和手势轨迹、水波纹效果
- 自定义控件三部曲之绘图篇——Path之贝赛尔曲线和手势轨迹、水波纹效果
- Android 之自定义view实现水波纹效果
- Android自定义View之水波纹显示进度效果
- Android 自定义view实现水波纹效果
- android:模拟水波效果的自定义View
- Android:自定义View实现水波进度效果
- android 自定义view实现水波纹效果
- Android 自定义view实现水波纹效果
- Android 自定义view实现水波纹效果
- Android自定义View实现水波浪效果
- Android 自定义view实现水波纹效果
- 习题为例学习K近邻简单实现
- BP算法从原理到python实现
- 遍历与复制数组
- 我的第一个Python+Appium脚本之APP登录脚本
- 腾讯云root用户
- Android自定义View之使用Path绘制手势轨迹和水波效果
- net-snmp开发过程整理-简介
- LeetCode160. Intersection of Two Linked Lists
- 理解泰勒公式·漫画
- Android 通用流行框架大全
- Matlab:不包含边界和工具栏的figure(移除保存图片的白边)
- 文件的创建、关闭及相关指令
- 最小二乘法及算法实现
- php 去掉图片的宽度、高度设置