Skip to content

Gestures 馃帀

Choose a tag to compare

@MihaelIsaev MihaelIsaev released this 17 Apr 21:38
· 288 commits to master since this release

Tested, Fixed and Improved all the gestures

We support all available gestures

TapGestureRecognizer

TapGestureRecognizer(taps: 1, touches: 1)

or

TapGestureRecognizer()
    .numberOfTapsRequired(1)
    .numberOfTouchesRequired(1)

馃挕numberOfTapsRequired and numberOfTouchesRequired also accept @State

also you can conveniently call onTapGesture at any view

.onTapGesture {}
.onTapGesture { view in }
.onTapGesture { view, state in }
.onTapGesture { view, state, recognizer in }
.onTapGesture(taps: 1, touches: 1) { view, state in }
.onTapGesture(taps: 1, touches: 1) { view, state, recognizer in }
.onTapGesture(taps: 1, touches: 1, $someState)
.onTapGesture(taps: 1, touches: 1, on: .ended) { }
.onTapGesture(taps: 1, touches: 1, on: .ended) { view in }

LongPressGestureRecognizer

LongPressGestureRecognizer(taps: 0, touches: 1, minDuration: nil, allowableMovement: nil)

or

LongPressGestureRecognizer(taps: 0, touches: 1)
    .minimumPressDuration(500)
    .allowableMovement(10)

馃挕minimumPressDuration and allowableMovement also accept @State

also you can conveniently call onLongPressGesture at any view

.onLongPressGesture { view in }
.onLongPressGesture { view, state in }
.onLongPressGesture { view, state, recognizer in }
.onLongPressGesture(taps: 1, touches: 1) { view, state in }
.onLongPressGesture(taps: 1, touches: 1) { view, state, recognizer in }
.onLongPressGesture(taps: 1, touches: 1, $someState)
.onLongPressGesture(taps: 1, touches: 1, on: .ended) { }
.onLongPressGesture(taps: 1, touches: 1, on: .ended) { view in }

PinchGestureRecognizer

PinchGestureRecognizer(scale: 10)

or

PinchGestureRecognizer().scale(10)

馃挕scale also accept @State

also you can conveniently call onPinchGesture at any view

// there are a lot of convenient combinations of this method
.onPinchGesture { view, state, recognizer in
    print("changed scale: \(recognizer.scale) velocity: \(recognizer.velocity)")
    view.size(200 * r.scale)
}

RotationGestureRecognizer

RotationGestureRecognizer(rotation: 2)

or

RotationGestureRecognizer().rotation(2)

馃挕rotation also accept @State

also you can conveniently call onRotationGesture at any view

// there are a lot of convenient combinations of this method
.onRotationGesture { view, state, recognizer in
    if state == .changed {
        view.transform = CGAffineTransform(rotationAngle: recognizer.rotation)
    }
}

SwipeGestureRecognizer

SwipeGestureRecognizer(direction: .left, touches: nil)

or

SwipeGestureRecognizer(direction: .left)
    .numberOfTouchesRequired(1)

馃挕numberOfTouchesRequired also accept @State

also you can conveniently call onSwipeGesture at any view

// there are a lot of convenient combinations of this method
.onSwipeGesture(direction: .left) { view, state, recognizer in }

PanGestureRecognizer

PanGestureRecognizer(minTouches: 1, maxTouches: 2)

or

PanGestureRecognizer()
    .minimumNumberOfTouches(1)
    .maximumNumberOfTouches(1)

馃挕minimumNumberOfTouches and maximumNumberOfTouches also accept @State

also you can conveniently call onPanGesture at any view

// there are a lot of convenient combinations of this method
.onPanGesture { view, state, recognizer in }

ScreenEdgePanGestureRecognizer

ScreenEdgePanGestureRecognizer(edges: .all)

and additional .edges method gives you an ability to change edges property later

.edges(.left)

馃挕edges also accept @State

also you can conveniently call onScreenEdgePanGesture at any view

// there are a lot of convenient combinations of this method
.onScreenEdgePanGesture(edges: .left) { view, state, recognizer in }

HoverGestureRecognizer

HoverGestureRecognizer()

you can conveniently call onHoverGesture or hovered at any view

.hovered {
    print("hovered: \($0)")
}

or

.onHoverGesture { view, state, recognizer in
        switch state {
        case .began: 
            print("began")
            view.backgroundColor = .magenta
        case .changed: 
            print("changed") 
            view.backgroundColor = .orange
        case .ended: 
            print("ended") 
            view.backgroundColor = .green
        default: print("default")
        }
}

State tracking

Any gesture recognizer has tracking methods

There are universal trackState method which contains state and optionally recognizer

.trackState { state, recognizer in
    // do switch/case here
}

馃挕trackState can accept @State

And additionally you have an ability to listen for exact state easily 馃憤

.onPossible { recognizer in }
.onBegan { recognizer in }
.onChanged { recognizer in }
.onEnded { recognizer in }
.onCancelled { recognizer in }
.onFailed { recognizer in }

馃挕recognizer is optional

Delegate

Any gesture recognizer has its delegate methods available directly

You can set delegate simply like this

.delegate(...)

Additionally you can use these convenient methods below and even combine them with the classic delegate

.shouldBegin { recognizer in
    return true
}
.shouldReceivePress { recognizer, press in
    return true
}
.shouldReceiveTouch { recognizer, touch in
    return true
}
.shouldRequireFailureOfOtherGestureRecognizer { currentRecognizer, otherRecognizer in
    return false
}
.shouldBeRequiredToFailByOtherGestureRecognizer { currentRecognizer, otherRecognizer in
    return false
}
.shouldRecognizeSimultaneouslyWithOtherGestureRecognizer { currentRecognizer, otherRecognizer in
    return true
}

How to add a gesture to view

UView().gesture(myGesture)

or

UView().gestures(myGesture1, myGesture2)

or even

UView().gestures {
    myGesture1
    myGesture2
    // unlimited amount
}

Multiple gestures at the same time (simple example for pinch + rotate)

UView().size(200).background(.red).centerInSuperview().gestures { v in
    PinchGestureRecognizer().shouldRecognizeSimultaneouslyWithOtherGestureRecognizer { og in
        print("PinchGestureRecognizer shouldRecognizeSimultaneouslyWith: \(og.tag)")
        return true
    }.trackState { s, r in
        if s == .changed {
            v.size(200 * r.scale)
        }
    }.tag(3)
    RotationGestureRecognizer().shouldRecognizeSimultaneouslyWithOtherGestureRecognizer { og in
        print("PinchGestureRecognizer shouldRecognizeSimultaneouslyWith: \(og.tag)")
        return true
    }.trackState { s, r in
        if s == .changed {
            v.transform = CGAffineTransform(rotationAngle: r.rotation)
        }
    }.tag(4)
}

View's touch methods which available without gesture recognizers

.touchesBegan { view, touch, event in }
.touchesMoved { view, touch, event in }
.touchesEnded { view, touch, event in }
.touchesCancelled { view, touch, event in }

馃挕 All the methods above has its convenient shorter variations