Android Canvas绘制贝塞尔连接线条时如何去除连接处的多余线段?
修复方案
核心问题原因
- 控件中心点计算错误:Y轴中心错误使用了控件宽度
getWidth()计算,控件非正方形时端点错位,出现多余线条痕迹 - Paint样式配置错误:若Paint使用填充模式,Path会自动生成闭合边,表现为多余连线
- 分段绘制Path:多次调用
drawPath绘制单段曲线,衔接处笔触叠加会产生多余痕迹
修改步骤
- 修正Paint配置,确保仅描边模式,配置好抗锯齿和衔接样式(Paint初始化放在构造方法中,不要重复创建)
// 在自定义View的构造方法中调用该方法初始化Paint private void initPaint() { mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); // 核心配置:仅描边,禁用填充 mPaint.setStrokeWidth(5f); // 可自行调整线宽 mPaint.setAntiAlias(true); // 开启抗锯齿 mPaint.setStrokeJoin(Paint.Join.ROUND); // 线条衔接处用圆角,避免生硬缺口 mPaint.setColor(Color.RED); // 可自行调整线条颜色 }
- 修复中心点计算逻辑,Y轴中心使用控件高度
getHeight()计算
private Point[] initPoint() { Point[] points = new Point[6]; int[] location1 = {(int) mOneView.getX(), (int) mOneView.getY()}; int[] location2 = {(int) mTwoView.getX(), (int) mTwoView.getY()}; int[] location3 = {(int) mThreeView.getX(), (int) mThreeView.getY()}; int[] location4 = {(int) mFourView.getX(), (int) mFourView.getY()}; int[] location5 = {(int) mFiveView.getX(), (int) mFiveView.getY()}; int[] location6 = {(int) mSixView.getX(), (int) mSixView.getY()}; // 修复Y轴中心点计算错误,替换getWidth()为getHeight() points[0] = new Point(location1[0] + mOneView.getWidth() / 2, location1[1] + mOneView.getHeight() / 2); points[1] = new Point(location2[0] + mTwoView.getWidth() / 2, location2[1] + mTwoView.getHeight() / 2); points[2] = new Point(location3[0] + mThreeView.getWidth() / 2, location3[1] + mThreeView.getHeight() / 2); points[3] = new Point(location4[0] + mFourView.getWidth() / 2, location4[1] + mFourView.getHeight() / 2); points[4] = new Point(location5[0] + mFiveView.getWidth() / 2, location5[1] + mFiveView.getHeight() / 2); points[5] = new Point(location6[0] + mSixView.getWidth() / 2, location6[1] + mSixView.getHeight() / 2); return points; }
- 优化Path绘制逻辑,所有曲线加入同一个Path后统一绘制
protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); Point[] points = initPoint(); Path path = new Path(); // 定位到起始点 path.moveTo(points[0].x, points[0].y); for (int i = 0; i < points.length - 1; i++) { Point startp = points[i]; Point endp = points[i + 1]; int wt = (startp.x + endp.x) / 2; Point p3 = new Point(wt, startp.y); Point p4 = new Point(wt, endp.y); path.cubicTo(p3.x, p3.y, p4.x, p4.y, endp.x, endp.y); } // 统一绘制全段路径,仅调用一次drawPath canvas.drawPath(path, mPaint); }
可选兼容方案
如果以上修改后仍存在多余线段,可在自定义View构造方法中添加以下代码关闭硬件加速即可:
setLayerType(LAYER_TYPE_SOFTWARE, null);
内容的提问来源于stack exchange,提问作者user7916816
相关产品推荐
相关产品推荐

