Swift中如何在两个UIView中心点之间添加连线?
在两个UIView中心点之间添加连线的实现方法
下面是两种实用的iOS实现方案,适配布局变化场景:
方案一:用CAShapeLayer实现(推荐,性能更优)
通过形状图层绘制连线,适合需要频繁更新的场景:
// 假设redView、greenView是已存在的目标视图,parentView是它们的共同父视图 func addConnectingLine() { let lineLayer = CAShapeLayer() lineLayer.strokeColor = UIColor.blue.cgColor lineLayer.lineWidth = 2.0 // 转换两个视图的中心点到父视图坐标系 let redCenter = redView.convert(redView.center, to: parentView) let greenCenter = greenView.convert(greenView.center, to: parentView) // 创建两点连线路径 let path = UIBezierPath() path.move(to: redCenter) path.addLine(to: greenCenter) lineLayer.path = path.cgPath parentView.layer.addSublayer(lineLayer) } // 处理布局变化(比如屏幕旋转、视图尺寸调整),在父视图的layoutSubviews中更新路径 override func layoutSubviews() { super.layoutSubviews() guard let lineLayer = self.layer.sublayers?.first(where: { $0 is CAShapeLayer }) as? CAShapeLayer else { return } let redCenter = redView.convert(redView.center, to: self) let greenCenter = greenView.convert(greenView.center, to: self) let updatedPath = UIBezierPath() updatedPath.move(to: redCenter) updatedPath.addLine(to: greenCenter) lineLayer.path = updatedPath.cgPath }
方案二:自定义UIView重绘实现
通过重写draw(_:)方法绘制连线,适合简单静态场景:
class ConnectingLineView: UIView { var startPoint: CGPoint = .zero var endPoint: CGPoint = .zero var lineColor: UIColor = .blue var lineWidth: CGFloat = 2.0 override func draw(_ rect: CGRect) { super.draw(rect) guard let context = UIGraphicsGetCurrentContext() else { return } context.setStrokeColor(lineColor.cgColor) context.setLineWidth(lineWidth) context.move(to: startPoint) context.addLine(to: endPoint) context.strokePath() } } // 使用方式 let lineView = ConnectingLineView(frame: parentView.bounds) lineView.startPoint = redView.convert(redView.center, to: parentView) lineView.endPoint = greenView.convert(greenView.center, to: parentView) parentView.addSubview(lineView) // 布局变化时更新 override func layoutSubviews() { super.layoutSubviews() lineView.startPoint = redView.convert(redView.center, to: self) lineView.endPoint = greenView.convert(greenView.center, to: self) lineView.setNeedsDisplay() }
注意事项
- 必须通过
convert(_:to:)方法转换坐标系,避免因视图层级导致的坐标偏差 - 如果视图有动态位置变化(比如动画移动),需要在变化完成后重新计算路径并更新
内容的提问来源于stack exchange,提问作者Akash Neeli
相关产品推荐
相关产品推荐

