如何通过滑动操作绘制无硬棱角的平滑圆形路径?
问题原因
当前你绘制的路径出现硬棱角,核心是ACTION_MOVE事件中直接调用lineTo()连接相邻的触摸采样点。Android触摸事件采样频率有限,滑动速度较快时采样点间隔较大,直接连接成直线就会出现明显的折线棱角。你已经配置了画笔的圆角、抗锯齿属性,问题不在画笔配置。
解决方案
改用二阶贝塞尔曲线连接触摸点,实现路径平滑效果,修改步骤如下:
- 新增全局成员变量记录上一次触摸坐标
private float mLastX; private float mLastY;
- 修改触摸事件处理逻辑,替换
lineTo()为quadTo()实现平滑连接
public boolean onTouch(View view, MotionEvent motionEvent) { int action = motionEvent.getAction(); float x = motionEvent.getX(); float y = motionEvent.getY(); switch (action) { case MotionEvent.ACTION_DOWN: mPath.reset(); mPath.moveTo(x, y); // 按下时初始化上一次坐标 mLastX = x; mLastY = y; break; case MotionEvent.ACTION_MOVE: Log.d(TAG, "onT:-> x " + x + " y-> " + y); // 取两次触摸点中点作为贝塞尔曲线终点,上一次触摸点作为控制点 float controlX = mLastX; float controlY = mLastY; float endX = (mLastX + x) / 2; float endY = (mLastY + y) / 2; mPath.quadTo(controlX, controlY, endX, endY); // 更新上一次坐标为当前坐标 mLastX = x; mLastY = y; view.invalidate(); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // 补全最后一段路径 mPath.lineTo(mLastX, mLastY); mPaths.add(new CurrentDraw(mPath, mPaint)); mPath.reset(); view.invalidate(); return false; } return true; }
可选优化
如果需要进一步提升平滑度,可以增加两个优化逻辑:
- 利用
MotionEvent.getHistorySize()获取触摸事件的历史采样点,遍历所有历史点参与路径计算,提升采样密度 - 对连续3-5个触摸点做加权平均滤波,过滤触摸抖动带来的微小路径毛刺
内容的提问来源于stack exchange,提问作者EAS
相关产品推荐
相关产品推荐

