Voltar ao ranking

RxSwiftCommunity/RxGesture

Swift

RxSwift reactive wrapper for view gestures

rxswiftrecognizersgesturepanswipeclick
Crescimento de estrelas
Estrelas
1.4k
Forks
181
Crescimento semanal
Issues
3
5001k
mar. de 2016ago. de 2019fev. de 2023jul. de 2026
README

RxGesture

Version License Platform

Usage

To run the example project, clone the repo, in the Example folder open RxGesture.xcworkspace.

You might need to run pod install from the Example directory first.


RxGesture allows you to easily turn any view into a tappable or swipeable control like so:

view.rx
  .tapGesture()
  .when(.recognized)
  .subscribe(onNext: { _ in
    //react to taps
  })
  .disposed(by: stepBag)

You can also react to more than one gesture. For example to dismiss a photo preview you might want to do that when the user taps it, or swipes up or down:

view.rx
  .anyGesture(.tap(), .swipe([.up, .down]))
  .when(.recognized)
  .subscribe(onNext: { _ in
    //dismiss presented photo
  })
  .disposed(by: stepBag)

rx.gesture is defined as Observable<G> where G is the actual type of the gesture recognizer so what it emits is the gesture recognizer itself (handy if want to call methods like asLocation(in view:) or asTranslation(in view:))

On iOS, RxGesture supports:

view.rx.tapGesture()           -> ControlEvent<UITapGestureRecognizer>
view.rx.pinchGesture()         -> ControlEvent<UIPinchGestureRecognizer>
view.rx.swipeGesture(.left)    -> ControlEvent<UISwipeGestureRecognizer>
view.rx.panGesture()           -> ControlEvent<UIPanGestureRecognizer>
view.rx.longPressGesture()     -> ControlEvent<UILongPressGestureRecognizer>
view.rx.rotationGesture()      -> ControlEvent<UIRotationGestureRecognizer>
view.rx.screenEdgePanGesture() -> ControlEvent<UIScreenEdgePanGestureRecognizer>
view.rx.hoverGesture()         -> ControlEvent<UIHoverGestureRecognizer>

view.rx.anyGesture(.tap(), ...)           -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.pinch(), ...)         -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.swipe(.left), ...)    -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.pan(), ...)           -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.longPress(), ...)     -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.rotation(), ...)      -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.screenEdgePan(), ...) -> ControlEvent<UIGestureRecognizer>
view.rx.anyGesture(.hover(), ...)         -> ControlEvent<UIGestureRecognizer>

On macOS, RxGesture supports:

view.rx.clickGesture()         -> ControlEvent<NSClickGestureRecognizer>
view.rx.rightClickGesture()    -> ControlEvent<NSClickGestureRecognizer>
view.rx.panGesture()           -> ControlEvent<NSPanGestureRecognizer>
view.rx.pressGesture()         -> ControlEvent<NSPressGestureRecognizer>
view.rx.rotationGesture()      -> ControlEvent<NSRotationGestureRecognizer>
view.rx.magnificationGesture() -> ControlEvent<NSMagnificationGestureRecognizer>

view.rx.anyGesture(.click(), ...)         -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.rightClick(), ...)    -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.pan(), ...)           -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.press(), ...)         -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.rotation(), ...)      -> ControlEvent<NSGestureRecognizer>
view.rx.anyGesture(.magnification(), ...) -> ControlEvent<NSGestureRecognizer>

ℹ️ If you use a gesture recognizer alone, prefer the view.rx.fooGesture() syntax over view.rx.anyGesture(.foo()) because it returns the concrete UIGestureRecognizer subclass and avoid you to cast it in subscribe().

Filtering State

By default, there is no filter on the state of the gesture recognizer. That means that you will always receive a first event with the initial state of the gesture recognizer (almost always .possible).

Here are the preferred states that can be used for each kind of gestures (iOS and macOS):

Kind States
.tap() .click() .rightClick() .swipe() .recognized
.longPress() .press() .began
.pan() .pinch() .rotation() .magnification() .screenEdgePan() .began .changed .ended

You usually filter the state using the .when() operator:

view.rx.tapGesture().when(.recognized)
view.rx.panGesture().when(.began, .changed, .ended)

If you are observing multiple gestures at once, you can use the .when() operator if you want to filter against the same state for all gesture recognizers, or use the tuple syntax for individual filtering:

view.rx
  .anyGesture(.tap(), .swipe([.up, .down]))
  .when(.recognized)
  .subscribe(onNext: { gesture in
    // Called whenever a tap, a swipe-up or a swipe-down is recognized (state == .recognized)
  })
  .disposed(by: bag)

view.rx
  .anyGesture(
    (.tap(), when: .recognized),
    (.pan(), when: .ended)
  )
  .subscribe(onNext: { gesture in
    // Called whenever:
    // - a tap is recognized (state == .recognized)
    // - or a pan is ended (state == .ended)
  })
  .disposed(by: bag)

The demo app includes examples for all recognizers ➡️ iOS, macOS.

Delegate customization

Lightweight customization

Each gesture recognizer has a default RxGestureRecognizerDelegate. It allows you to customize every delegate method using a policy:

  • .always will return true to the corresponding delegate method
  • .never will return false to the corresponding delegate method
  • .custom takes an associated closure that will be executed to return a value to the corresponding delegate method

Here are the available policies with their corresponding delegate method:

beginPolicy                   -> gestureRecognizerShouldBegin(:_)
touchReceptionPolicy          -> gestureRecognizer(_:shouldReceive:)
selfFailureRequirementPolicy  -> gestureRecognizer(_:shouldBeRequiredToFailBy:)
otherFailureRequirementPolicy -> gestureRecognizer(_:shouldRequireFailureOf:)
simultaneousRecognitionPolicy -> gestureRecognizer(_:shouldRecognizeSimultaneouslyWith:)
eventRecognitionAttemptPolicy -> gestureRecognizer(_:shouldAttemptToRecognizeWith:) // macOS only
pressReceptionPolicy          -> gestureRecognizer(_:shouldReceive:) // iOS only

This delegate can be customized in the configuration closure:

view.rx.tapGesture(configuration: { gestureRecognizer, delegate in
  delegate.simultaneousRecognitionPolicy = .always // (default value)
  // or
  delegate.simultaneousRecognitionPolicy = .never
  // or
  delegate.simultaneousRecognitionPolicy = .custom { gestureRecognizer, otherGestureRecognizer in
    return otherGestureRecognizer is UIPanGestureRecognizer
  }
  delegate.otherFailureRequirementPolicy = .custom { gestureRecognizer, otherGestureRecognizer in
    return otherGestureRecognizer is UILongPressGestureRecognizer
  }
})

Default values can be found in RxGestureRecognizerDelegate.swift.

Full customization

You can also replace the default delegate by your own, or remove it.

view.rx.tapGesture { [unowned self] gestureRecognizer, delegate in
  gestureRecognizer.delegate = nil
  // or
  gestureRecognizer.delegate = self
}

Requirements

This library depends on both RxSwift and RxCocoa.

Installation

CocoaPods

Add this to Podfile

pod "RxGesture"
$ pod install

Carthage

Add this to Cartfile

github "RxSwiftCommunity/RxGesture" ~> 3.0
$ carthage update

Thanks

Everyone in the RxSwift Slack channel 💯

License

RxGesture is available under the MIT license. See the LICENSE file for more info.

Repositórios relacionados
ReactiveX/RxSwift

Reactive Programming in Swift

SwiftMIT Licenseswiftreactivex
24.6k4.2k
Moya/Moya

Network abstraction layer written in Swift.

SwiftMIT Licenseswiftreactiveswift
moya.github.io
15.4k2k
Finb/Bark

Bark is an iOS App which allows you to push custom notifications to your iPhone

SwiftMIT Licenseiosios-app
bark.day.app
8.8k670
sergdort/CleanArchitectureRxSwift

Example of Clean Architecture of iOS app using RxSwift

Swiftiosreactive-programming
3.9k496
hilen/TSWeChat

A WeChat alternative. Written in Swift 5.

SwiftMIT Licenseuiwechat
3.8k785
lanceylai/TSWeChat

A WeChat alternative. Written in Swift 5.

SwiftMIT Licenseuiwechat
3.7k772
khoren93/SwiftHub

GitHub iOS client in RxSwift and MVVM-C clean architecture

SwiftMIT Licenserxswiftmoya
3.1k541
RxSwiftCommunity/RxDataSources

UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates, editing ...)

SwiftMIT Licenserxswiftdatasource
3.1k494
ReactorKit/ReactorKit

A library for reactive and unidirectional Swift applications

SwiftMIT Licenseswiftreactorkit
reactorkit.io
2.8k271
QuickBirdEng/XCoordinator

🎌 Powerful navigation library for iOS based on the coordinator pattern

SwiftMIT Licenserxswiftrxswift-extensions
2.4k191
pakerwreah/Calendr

Menu bar calendar for macOS - MVVM | RxSwift | AppKit | SwiftUI

SwiftMIT Licensecalendarmacos
2.3k92
CombineCommunity/rxswift-to-combine-cheatsheet

RxSwift to Apple’s Combine Cheat Sheet

RubyRubyGemsMIT Licenserxswiftcombine
medium.com/gett-engineering/rxswift-to-apples-combine-cheat-sheet-e9ce32b14c5b
2.1k128