Android使用贝塞尔线高仿QQ聊天消息气泡的拖拽效果
16lz
2021-01-23
先画圆,都会吧。代码如下:
public class Bezier extends View { private final Paint mGesturePaint = new Paint(); private final Path mPath = new Path(); private float mX1 = 100, mY1 = 150; private float mX2 = 300, mY2 = 150; private boolean mBezier = true; private int mRadius = 30; public Bezier(Context context, AttributeSet attrs) { super(context, attrs); mGesturePaint.setAntiAlias(true); mGesturePaint.setStyle(Paint.Style.FILL_AND_STROKE); mGesturePaint.setStrokeWidth(5); mGesturePaint.setColor(Color.RED); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); canvas.drawCircle(mX1, mX2, mRadius, mGesturePaint); }}
效果
拖拽的另个一圆就不画了,效果的实现主要是计算两个点之间的拖拽区域,如下图:
求出区域之后,使用贝塞尔线画出效果就可以了,代码:
public class Bezier extends View { private final Paint mGesturePaint = new Paint(); private final Path mPath = new Path(); private float mX1 = 100, mY1 = 150; private float mX2 = 300, mY2 = 150; private boolean mBezier = true; private int mRadius = 30; public Bezier(Context context, AttributeSet attrs) { super(context, attrs); mGesturePaint.setAntiAlias(true); mGesturePaint.setStyle(Paint.Style.FILL_AND_STROKE); mGesturePaint.setStrokeWidth(5); mGesturePaint.setColor(Color.RED); setBezier(); } private void setBezier() { float offsetX = (float) (mRadius * Math.sin(Math.atan((mY2 - mY1) / (mX2 - mX1)))); float offsetY = (float) (mRadius * Math.cos(Math.atan((mY2 - mY1) / (mX2 - mX1)))); float x1 = mX1 - offsetX; float y1 = mY1 + offsetY; float x2 = mX2 - offsetX; float y2 = mY2 + offsetY; float x3 = mX2 + offsetX; float y3 = mY2 - offsetY; float x4 = mX1 + offsetX; float y4 = mY1 - offsetY; mPath.reset(); mPath.moveTo(x1, y1); mPath.quadTo((mX1 + mX2) / 2, (mY1 + mY2) / 2, x2, y2);//锚点直接取偏移量的一半 mPath.lineTo(x3, y3); mPath.quadTo((mX1 + mX2) / 2, (mY1 + mY2) / 2, x4, y4); mPath.lineTo(x1, y1); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); //通过画布绘制多点形成的图形 canvas.drawCircle(mX1, mY1, mRadius, mGesturePaint); if (mBezier) { canvas.drawPath(mPath, mGesturePaint); canvas.drawCircle(mX2, mY2, mRadius, mGesturePaint); } }}
效果图:
拖拽效果只要在onTouchEvent里动态改变拖动点的坐标重绘就可以实现了,代码:
public class Bezier extends View { private final Paint mGesturePaint = new Paint(); private final Path mPath = new Path(); private float mX1 = 100, mY1 = 150; private float mX2 = 300, mY2 = 150; private boolean mBezier = true; private int mRadius = 30; public Bezier(Context context, AttributeSet attrs) { super(context, attrs); mGesturePaint.setAntiAlias(true); mGesturePaint.setStyle(Paint.Style.FILL_AND_STROKE); mGesturePaint.setStrokeWidth(5); mGesturePaint.setColor(Color.RED); setBezier(); } private void setBezier() { float offsetX = (float) (mRadius * Math.sin(Math.atan((mY2 - mY1) / (mX2 - mX1)))); float offsetY = (float) (mRadius * Math.cos(Math.atan((mY2 - mY1) / (mX2 - mX1)))); float x1 = mX1 - offsetX; float y1 = mY1 + offsetY; float x2 = mX2 - offsetX; float y2 = mY2 + offsetY; float x3 = mX2 + offsetX; float y3 = mY2 - offsetY; float x4 = mX1 + offsetX; float y4 = mY1 - offsetY; mPath.reset(); mPath.moveTo(x1, y1); mPath.quadTo((mX1 + mX2) / 2, (mY1 + mY2) / 2, x2, y2);//锚点直接取偏移量的一半 mPath.lineTo(x3, y3); mPath.quadTo((mX1 + mX2) / 2, (mY1 + mY2) / 2, x4, y4); mPath.lineTo(x1, y1); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); //通过画布绘制多点形成的图形 canvas.drawCircle(mX1, mY1, mRadius, mGesturePaint); if (mBezier) { canvas.drawPath(mPath, mGesturePaint); canvas.drawCircle(mX2, mY2, mRadius, mGesturePaint); } } @Override public boolean onTouchEvent(MotionEvent event) { mX2 = event.getX(); mY2 = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mBezier = true; setBezier(); break; case MotionEvent.ACTION_MOVE: mBezier = true; setBezier(); break; case MotionEvent.ACTION_UP: mBezier = false; break; } invalidate(); return true; }}
源码
更多相关文章
- android中图片倒影、圆角效果重绘
- android 图片文字轮播效果(图片和文字自动滚动)
- Android Gallery3D效果 教程 案例 代码
- 如何在Activity调用surfaceView实现透明或半透明的效果
- TextView属性android:ellipsize实现跑马灯效果,TextView内容过长
- Android 中 drawTextOnPath 文字效果演示(中级)
- Android新姿势:3D翻转效果原理
- 我的Android进阶之旅------>Android利用温度传感器实现带动画效
- 模拟Android多点触控