ペイントアプリなんかでよくある、選択した範囲を動く点線で囲むサンプルです。また使いそうなのでメモ代わりに。
こういうやつ
仕組みは、点線の枠のオフセットをタイマーで変更して動いているように見せているだけです。簡単だけど、点線が動くだけですごくリッチな感じに見えますね。
ドラッグの処理はUIPanGestureRecognizerで行ってます。
ViewController.swift
import UIKit class ViewController: UIViewController { var panGestureRecognizer: UIPanGestureRecognizer! = nil var selectAreaView: SelectAreaView! = nil var selectStartPoint: CGPoint = CGPointZero override func viewDidLoad() { super.viewDidLoad() panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "dragView:") self.view.addGestureRecognizer(panGestureRecognizer) } override func viewDidDisappear(animated: Bool) { super.viewDidDisappear(animated) self.view.removeGestureRecognizer(panGestureRecognizer) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } func dragView(sender: UIPanGestureRecognizer) { if sender.state == UIGestureRecognizerState.Began { // ドラッグ開始 selectStartPoint = sender.locationInView(self.view) var frame = CGRectMake( selectStartPoint.x, selectStartPoint.y, 0, 0) selectAreaView = SelectAreaView(frame: frame) self.view.addSubview(selectAreaView) } else if sender.state == UIGestureRecognizerState.Changed { // ドラッグ中 var tapPoint = sender.translationInView(self.view) var frame: CGRect = CGRectZero if tapPoint.x > 0 && tapPoint.y > 0 { frame = CGRectMake( selectStartPoint.x, selectStartPoint.y, tapPoint.x, tapPoint.y) } else if tapPoint.x < 0 && tapPoint.y > 0 { frame = CGRectMake( selectStartPoint.x + tapPoint.x, selectStartPoint.y, fabs(tapPoint.x), tapPoint.y ) } else if tapPoint.x > 0 && tapPoint.y < 0 { frame = CGRectMake( selectStartPoint.x, selectStartPoint.y + tapPoint.y, tapPoint.x, fabs(tapPoint.y) ) } else if tapPoint.x < 0 && tapPoint.y < 0 { frame = CGRectMake( selectStartPoint.x + tapPoint.x, selectStartPoint.y + tapPoint.y, fabs(tapPoint.x), fabs(tapPoint.y) ) } selectAreaView.changeFrame(frame) } else if sender.state == UIGestureRecognizerState.Ended { // ドラッグ終了 selectAreaView.removeFromSuperview() } } }
こちらが動く点線枠のクラス
SelectAreaView.swift
import Foundation import UIKit class SelectAreaView: UIView { let segmentSize: CGFloat = 4.0 // 点線の線のサイズ let gapSize: CGFloat = 4.0 // 点線の間のサイズ var myTimer: NSTimer! = nil var phaseCount: CGFloat = 0.0 required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = UIColor.clearColor() myTimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: "phaseChange:", userInfo: nil, repeats: true) } deinit { if myTimer != nil { myTimer.invalidate() myTimer = nil } } func phaseChange(timer: NSTimer) { phaseCount += 1.0 if phaseCount >= segmentSize + gapSize { phaseCount = 0 } self.setNeedsDisplay() } override func drawRect(rect: CGRect) { var path = UIBezierPath() UIColor.blackColor().set() path.lineWidth = 1 var dashPattern = [segmentSize, gapSize] path.setLineDash(dashPattern, count:2, phase:phaseCount) path.moveToPoint(CGPointZero) path.addLineToPoint(CGPointMake(self.frame.size.width, 0)) path.addLineToPoint(CGPointMake(self.frame.size.width, self.frame.size.height)) path.addLineToPoint(CGPointMake(0, self.frame.size.height)) path.addLineToPoint(CGPointMake(0, 0)) path.stroke() } func changeFrame(frame: CGRect) { self.frame = frame self.setNeedsDisplay() } }