Slide 1

Slide 1 text

Custom Gesture Recognizer @TachibanaKaoru 2020/4/27 potatotips #69

Slide 2

Slide 2 text

About Me @TachibanaKaoru Freelance iOS Engineer

Slide 3

Slide 3 text

Gesture Recognizer

Slide 4

Slide 4 text

Default Gesture Recognizers UITapGestureRecognizer UISwipeGestureRecognizer UIRotationGestureRecognizer ....

Slide 5

Slide 5 text

Limitation of Default Gesture δΣενϟʔ͕ೝࣝ͞Ε͍ͯΔ్தͰͳʹ͔ॲཧΛ͍ͨ͠ɻ ಠࣗͷετϩʔΫͰೖྗ͍ͨ͠ɻ

Slide 6

Slide 6 text

ͦ͜Ͱ Custom Gesture Recognizer !

Slide 7

Slide 7 text

GestureRecognizerͷ͘͠Έ શମͷྲྀΕ view ͷλονΠϕϯτͷ଎౓΍ํ޲Λղੳ͢Δɻ ҙਤͨ͠଎౓ɾํ޲ͳΒδΣενϟʔೝࣝΛଓ͚ɺͦ͏Ͱͳ͚Ε͹ऴ ྃ͢Δɻ δΣενϟʔ͕ೝࣝͰ͖ͨΒ delegate ʹ recognizedΠϕϯτΛૹ৴͢ Δɻ

Slide 8

Slide 8 text

Tracking of UITouch

Slide 9

Slide 9 text

UITouch open class UITouch : NSObject { open var timestamp: TimeInterval { get } open var tapCount: Int { get } open var type: UITouch.TouchType { get } open func location(in view: UIView?) -> CGPoint open func previousLocation(in view: UIView?) -> CGPoint }

Slide 10

Slide 10 text

velocity vector with UITouch location previousLocation

Slide 11

Slide 11 text

velocity vector with UITouch location previousLocation (x1 , y1 )

Slide 12

Slide 12 text

velocity vector with UITouch location previousLocation (x1 , y1 ) (x2 , y2 )

Slide 13

Slide 13 text

velocity vector with UITouch location previousLocation (x1 , y1 ) (x2 , y2 ) ( x2 − x1 t2 − t1 , y2 − y1 t2 − t1 ) 2఺ؒͷ଎౓ϕΫτϧ

Slide 14

Slide 14 text

velocity vector with UITouch location previousLocation (x1 , y1 ) (x2 , y2 ) ( x2 − x1 t2 − t1 , y2 − y1 t2 − t1 ) 2఺ؒͷ଎౓ϕΫτϧ (x2 − x1 , y2 − y1 ) 2఺ؒͷ୯Ґ࣌ؒ͋ͨΓͷ଎౓ϕΫτϧ

Slide 15

Slide 15 text

struct Velocity { var vx: CGFloat var vy: CGFloat } extension UITouch{ func velocity(in view: UIView?) -> Velocity{ let location = location(in: view) let previousLocation = previousLocation(in: view) let distanceX = location.x - previousLocation.x let distanceY = location.y - previousLocation.y let velocity = Velocity(vx: distanceX, vy: distanceY) return velocity }

Slide 16

Slide 16 text

gradient of UITouch location previousLocation (x1 , y1 ) (x2 , y2 ) θ

Slide 17

Slide 17 text

gradient of UITouch location previousLocation (x1 , y1 ) (x2 , y2 ) θ vx vy

Slide 18

Slide 18 text

gradient of UITouch location previousLocation (x1 , y1 ) (x2 , y2 ) θ vx vy tan θ = vy vx

Slide 19

Slide 19 text

gradient of UITouch location previousLocation (x1 , y1 ) (x2 , y2 ) θ vx vy tan θ = vy vx θ = tan−1 vy vx

Slide 20

Slide 20 text

struct Velocity { var vx: CGFloat var vy: CGFloat var gradient: CGFloat{ // ࣮ࡍʹ͸ɺvyɺvx͕0ͷ࣌ͷॲཧ͓Αͼɺgradient஋͕ 0-2πʹͳΔΑ͏ͳ // ਖ਼نԽΛߦ͍·͢ var calcGradient = atan(vy / vx) return calcGradient }

Slide 21

Slide 21 text

Radian ހ౓๏ 360° = 2 π radian

Slide 22

Slide 22 text

π 2 0 π 3π 2

Slide 23

Slide 23 text

π 2 0 π 3π 2 π 4

Slide 24

Slide 24 text

π 2 0 π 3π 2 3π 4

Slide 25

Slide 25 text

Tracking of UITouch ͜ΕͰɺUITouch͔Βɺ଎౓ϕΫτϧͱ܏͖ (gradient) ͕Θ͔ΔΑ͏ʹͳ Γ·ͨ͠ɻ

Slide 26

Slide 26 text

How to handle gesture state Custom Gesture RecognizerͰ͸ɺԼهͷ2छྨͷঢ়ଶΛ؅ཧ͠·͢ɻ δΣενϟʔͷશମঢ়ଶ (UIGestureRecognizer.State) ܧଓ or ࣦഊ or ੒ޭ ετϩʔΫͷ൑அ શମͷͲͷ෦෼Λೝࣝதͳͷ͔

Slide 27

Slide 27 text

UIGestureRecognizer.State open class UIGestureRecognizer : NSObject { // the current state of the gesture recognizer open var state: UIGestureRecognizer.State { get } }

Slide 28

Slide 28 text

class MyGestureRecognizer: UIGestureRecognizer{ override func touchesBegan(_ touches: Set, with event: UIEvent) { } override func touchesMoved(_ touches: Set, with event: UIEvent) { } override func touchesEnded(_ touches: Set, with event: UIEvent) { } override func touchesCancelled(_ touches: Set, with event: UIEvent) { } override func reset() { } }

Slide 29

Slide 29 text

Handling touch event t

Slide 30

Slide 30 text

Handling touch event touchesBegan t touchesMoved touchesEnd

Slide 31

Slide 31 text

touchesBegan t touchesMoved touchesEnd

Slide 32

Slide 32 text

Possible Recognized Failed Possible gestureॲཧܧଓ gestureॲཧऴྃ gestureॲཧऴྃ

Slide 33

Slide 33 text

P F P P P P R F F touchesBegan touchesMoved touchesEnd

Slide 34

Slide 34 text

ετϩʔΫͷ൑அ ετϩʔΫͷ܏͖͔Βɺೝ͍ࣝͨ͠δΣενϟʔͲͷετϩʔΫʹͳͷ ͔Λ൑அ͢Δɻ ෳ਺ͷετϩʔΫ͔Βߏ੒͞ΕΔδΣενϟʔ΋͋Δ

Slide 35

Slide 35 text

ೋͭͷ࿈ଓͨ͠ετϩʔΫ͔Βߏ੒͞ΕΔ৔߹

Slide 36

Slide 36 text

δΣενϟʔ։࢝ ӈԼ΁ͷετϩʔΫ ӈ্΁ͷετϩʔΫ δΣενϟʔ׬ྃ

Slide 37

Slide 37 text

P F P P P P R F F touchesBegan touchesMoved touchesEnd

Slide 38

Slide 38 text

ೋͭͷ࿈ଓ͠ͳ͍ετϩʔΫ͔Β ߏ੒͞ΕΔ৔߹

Slide 39

Slide 39 text

ӈԼ΁ͷετϩʔΫ͔Β࢝·Δύλʔϯ ࠨԼ΁ͷετϩʔΫ͔Β࢝·Δύλʔϯ

Slide 40

Slide 40 text

P F P P P F touchesBegan touchesMoved touchesEnd touchesEnd touchesMoved touchesMoved touchesBegan R F P P

Slide 41

Slide 41 text

·ͱΊ Custom Gesture Recognizerͷ࣮૷͸ҙ֎ͱ؆୯Ͱ͢ɻ ͨͩ͠ɺετϩʔΫʹΑͬͯ͸ɺϢʔβʔͷೖྗΛҙਤ௨Γʹ൑அ͢Δ ͷ͕೉͍͠৔߹΋͋ΔͨΊɺঢ়گʹԠͨ͡࠷దԽ͕ඞཁɻ αϯϓϧ͕ͪ͜Βʹ͋ΔͷͰɺΑ͔ͬͨΒݟͯΈ͍ͯͩ͘͞ɻ https://github.com/TachibanaKaoru/CustomGestureRecognizer