Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách vẽ đường nét đứt (dotted/dashed line) trong iOS

Đường nét đứt dùng cho: form nhập liệu (dotted line signature), navigation route, divider, highlight zone...

Cách làm: CAShapeLayer + lineDashPattern

Bước 1: Tạo dự án

Xcode → Single View App → Tên: "DottedLine".

Bước 2: Storyboard

Thêm UIView (container cho line) → Tạo @IBOutlet weak var dottedView: UIView!

Cách vẽ đường nét đứt (dotted/dashed line) trong iOS

Bước 3: Extension UIView


extension UIView {
    func drawDottedLine(width: CGFloat = 1.0, 
                        color: UIColor = .systemBlue,
                        dashPattern: [NSNumber] = [4, 4],
                        direction: DottedLineDirection = .horizontal) {
        
        // Xóa layer cũ (tránh vẽ đè khi gọi lại)
        layer.sublayers?.filter { $0 is CAShapeLayer }.forEach { $0.removeFromSuperlayer() }
        
        let shapeLayer = CAShapeLayer()
        shapeLayer.strokeColor = color.cgColor
        shapeLayer.lineWidth = width
        shapeLayer.lineDashPattern = dashPattern // [dash, gap, dash, gap...]
        shapeLayer.fillColor = UIColor.clear.cgColor
        
        let path = CGMutablePath()
        let startPoint: CGPoint
        let endPoint: CGPoint
        
        switch direction {
        case .horizontal:
            startPoint = CGPoint(x: 0, y: bounds.midY)
            endPoint = CGPoint(x: bounds.width, y: bounds.midY)
        case .vertical:
            startPoint = CGPoint(x: bounds.midX, y: 0)
            endPoint = CGPoint(x: bounds.midX, y: bounds.height)
        }
        
        path.move(to: startPoint)
        path.addLine(to: endPoint)
        shapeLayer.path = path
        
        layer.addSublayer(shapeLayer)
    }
}

enum DottedLineDirection {
    case horizontal
    case vertical
}

Bước 4: Gọi trong viewDidLoad


override func viewDidLoad() {
    super.viewDidLoad()
    
    // Đường ngang, cyan, nét 5, gap 3
    dottedView.drawDottedLine(width: 5.0, color: .systemCyan, dashPattern: [5, 3])
    
    // Ví dụ khác: đường dọc, đỏ, nét 10 gap 5
    // verticalView.drawDottedLine(width: 2, color: .systemRed, dashPattern: [10, 5], direction: .vertical)
}

Cách vẽ đường nét đứt (dotted/dashed line) trong iOS

Các pattern dashPattern phổ biến

Pattern Hiệu ứng
[2, 2] Chấm nhỏ dày đặc
[4, 4] Nét đứt chuẩn (default)
[10, 5] Nét dài, khoảng cách trung bình
[20, 10, 5, 10] Pattern phức tạp: nét dài - gap - nét ngắn - gap
[0, 10] Chấm tròn (cần lineCap = .round)

Nâng cao: Vẽ đường cong/dị dạng


func drawCurvedDottedLine(in view: UIView, points: [CGPoint], color: UIColor = .systemBlue) {
    let shapeLayer = CAShapeLayer()
    shapeLayer.strokeColor = color.cgColor
    shapeLayer.lineWidth = 2
    shapeLayer.lineDashPattern = [8, 4]
    shapeLayer.fillColor = UIColor.clear.cgColor
    shapeLayer.lineCap = .round
    
    let path = CGMutablePath()
    path.move(to: points[0])
    for i in 1..

Animation đường nét đứt (Marching Ants)


func animateDottedLine(_ shapeLayer: CAShapeLayer) {
    let animation = CABasicAnimation(keyPath: "lineDashPhase")
    animation.fromValue = 0
    animation.toValue = shapeLayer.lineDashPattern?.reduce(0) { $0 + $1.intValue } ?? 10
    animation.duration = 1.0
    animation.repeatCount = .infinity
    shapeLayer.add(animation, forKey: "marchingAnts")
}

Lưu ý

  • Gọi trong viewDidLayoutSubviews hoặc layoutSubviews nếu view size thay đổi (Auto Layout)
  • Xóa layer cũ trước khi vẽ mới tránh memory leak / visual glitch
  • lineCap = .round cho chấm tròn đẹp mắt
  • Performance: CAShapeLayer render GPU, rất nhẹ