# 拖拽效果
拖拽效果的实现其实是用贝塞尔曲线去构成的,这里上一张图就很明白
可以看到,所谓的拖拽效果只是在两个圆圈之间根据两个圆同侧切点和圆心连线中点三个点构建一条二阶贝塞尔曲线,另一侧也是,将其用颜色填充,就构成了qq红点的拖拽效果,是不是很简单
那么我们这里的目标就是先算出p0,p1,Q0三个点的坐标
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| float endX = nowFingerPoint.x; float endY = nowFingerPoint.y; float dx = endX - startX; float dy = endY - startY; float distance = (float) Math.sqrt(Math.pow(endY-startY, 2) + Math.pow(endX-startX, 2)); radius = 50 - distance/15; radius = radius<20 ? 20 : radius; double a = Math.atan(dy / dx); float offsetX = (float) (radius * Math.sin(a)); float offsetY = (float) (radius * Math.cos(a));
float x1 = startX - offsetX; float y1 = startY + offsetY; float x2 = endX - offsetX; float y2 = endY + offsetY; float x3 = endX + offsetX; float y3 = endY - offsetY; float x4 = startX + offsetX; float y4 = startY - offsetY;
|
- 然后要做的就是画两个圆点,以及把这四个点连起来构成贝塞尔曲线
1 2 3 4 5 6 7 8 9 10 11
| float anchorX = (startX + endX) / 2; float anchorY = (startY + endY) / 2; path.reset(); path.reset(); path.moveTo(x1, y1); path.quadTo(anchorX, anchorY, x2, y2); path.lineTo(x3, y3); path.quadTo(anchorX, anchorY, x4, y4); path.lineTo(x1, y1);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
| public class QQ_message_drag_effect extends View { public QQ_message_drag_effect(Context context) { super(context); } public QQ_message_drag_effect(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public QQ_message_drag_effect(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } int width; int height; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(width = ((ViewGroup)getParent()).getMeasuredWidth(),height = ((ViewGroup)getParent()).getMeasuredHeight()); } float radius = 50; PointF startPoint = new PointF(300,500); PointF nowFingerPoint = new PointF(); boolean isMoveing = false; Paint paint = new Paint(); Path path = new Path(); @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getX(); int y = (int) event.getY(); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: if((x < startPoint.x + radius && x > startPoint.x - radius) && (y < startPoint.y + radius && y > startPoint.y - radius)){ isMoveing = true; } break; case MotionEvent.ACTION_MOVE: if(isMoveing){ nowFingerPoint.y = y; nowFingerPoint.x = x; invalidate(); } break; case MotionEvent.ACTION_UP: isMoveing = false; radius = 50; invalidate(); break; } return true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); float startX = startPoint.x; float startY = startPoint.y; paint.setColor(Color.RED); canvas.drawCircle(startX,startY,radius,paint); if(isMoveing){ float endX = nowFingerPoint.x; float endY = nowFingerPoint.y; float dx = endX - startX; float dy = endY - startY; float distance = (float) Math.sqrt(Math.pow(endY-startY, 2) + Math.pow(endX-startX, 2)); radius = 50 - distance/15; radius = radius<20 ? 20 : radius; double a = Math.atan(dy / dx); float offsetX = (float) (radius * Math.sin(a)); float offsetY = (float) (radius * Math.cos(a)); float x1 = startX - offsetX; float y1 = startY + offsetY; float x2 = endX - offsetX; float y2 = endY + offsetY; float x3 = endX + offsetX; float y3 = endY - offsetY; float x4 = startX + offsetX; float y4 = startY - offsetY; float anchorX = (startX + endX) / 2; float anchorY = (startY + endY) / 2; path.reset(); path.reset(); path.moveTo(x1, y1); path.quadTo(anchorX, anchorY, x2, y2); path.lineTo(x3, y3); path.quadTo(anchorX, anchorY, x4, y4); path.lineTo(x1, y1); canvas.drawPath(path,paint); canvas.drawCircle(endX,endY,radius,paint); } } }
|
参考:https://blog.csdn.net/asffghfgfghfg1556/article/details/80409902