Draw a line that can stretch like the Xcode assistant editor in Swift

后端 未结 1 973
情歌与酒
情歌与酒 2021-01-07 08:03

When it comes to drawing lines in Swift, most solutions out there are to override the drawRect function in a UIView, but I\'m looking for a more dynamic way to draw a line.<

1条回答
  •  小鲜肉
    小鲜肉 (楼主)
    2021-01-07 08:57

    You can use UIPanGestureRecognizer to get gesture events and draw a CALayer with UIBezierPath.

    UIPanGestureRecognizer has some gesture states, in this case, we need to handle three states to draw the line. Let's separate the whole action into small pieces for more easier to figure out what to do.

    Before the start, there is one thing you have to know.

    // We can get current touch position via gesture recognizer.
    let currentPanPoint = panRecognizer.location(in: self.view)
    
    1. To get line start point and create a CALayer in state UIGestureRecognizerState.began.
    case .began:
        panGestureStartPoint = currentPanPoint
        self.view.layer.addSublayer(lineShape)
    
    1. Get line end point in state UIGestureRecognizerState.changed and create a UIBezierPath, assign the CGPath of UIBezierPath to CALayer to draw the line.
    case .changed:
        let linePath = UIBezierPath()
        linePath.move(to: panGestureStartPoint)
        linePath.addLine(to: currentPanPoint)
    
        lineShape.path = linePath.cgPath
    
    1. Remove the line from layout in state UIGestureRecognizerState.end.
    case .ended:
        lineShape.path = nil
        lineShape.removeFromSuperlayer()
    

    Combine the fragments above, here is the example code.

    class ViewController: UIViewController {
        @IBOutlet var dragFrom: UILabel!
    
        private lazy var lineShape: CAShapeLayer = {
            let lineShape = CAShapeLayer()
            lineShape.strokeColor = UIColor.blue.cgColor
            lineShape.lineWidth = 2.0
    
            return lineShape
        }()
        private var panGestureStartPoint: CGPoint = .zero
        private lazy var panRecognizer: UIPanGestureRecognizer = {
            return UIPanGestureRecognizer(target: self, action: #selector(panGestureCalled(_:)))
        }()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.dragFrom.addGestureRecognizer(panRecognizer)
        }
    
        // MARK: Selectors
        func panGestureCalled(_: UIPanGestureRecognizer) {
            let currentPanPoint = panRecognizer.location(in: self.view)
            switch panRecognizer.state {
            case .began:
                panGestureStartPoint = currentPanPoint
                self.view.layer.addSublayer(lineShape)
    
            case .changed:
                let linePath = UIBezierPath()
                linePath.move(to: panGestureStartPoint)
                linePath.addLine(to: currentPanPoint)
    
                lineShape.path = linePath.cgPath
            case .ended:
                lineShape.path = nil
                lineShape.removeFromSuperlayer()
            default: break
            }
        }
    }
    

    And it works like this. http://i.imgur.com/5JsFeoB.gifv

    If you wanna learn more details, this is the tutorial in Apple's Developer guides. Learn how to draw shapes using Bezier Path

    0 讨论(0)
提交回复
热议问题