RxGesture

Version License Platform

用法

要运行示例项目,请克隆 repo,在 Example 文件夹中打开 RxGesture.xcworkspace

可能需要先从 Example 目录运行 pod install


RxGesture 允许您轻松地将任何视图转换为可点击或可滑动控件,如下所示:

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

您还可以响应多个手势。例如,要关闭照片预览,您可能希望在用户点击它、或向上或向下滑动时执行此操作

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

rx.gesture 定义为 Observable<G>,其中 G 是手势识别器的实际类型,因此它发出的是手势识别器本身 (如果您想调用像 asLocation(in view:)asTranslation(in view:) 这样的方法,这将非常有用)

在 iOS 上,RxGesture 支持

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>

在 macOS 上,RxGesture 支持

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>

ℹ️ 如果您单独使用手势识别器,则首选使用 view.rx.fooGesture() 语法而不是 view.rx.anyGesture(.foo()),因为它返回具体的 UIGestureRecognizer 子类,并避免您在 subscribe() 中进行类型转换。

过滤状态

默认情况下,手势识别器的状态没有过滤器。 这意味着您将始终收到一个带有手势识别器初始状态的第一个事件(几乎总是 .possible)。

以下是每种手势的首选状态(iOSmacOS

类型 状态
.tap() .click() .rightClick() .swipe() .recognized
.longPress() .press() .began
.pan() .pinch() .rotation() .magnification() .screenEdgePan() .began .changed .ended

您通常使用 .when() 运算符过滤状态

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

如果您一次观察多个手势,如果您想针对所有手势识别器过滤相同的状态,您可以使用 .when() 运算符,或者使用元组语法进行单独过滤

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)

演示应用程序包含所有识别器的示例 ➡️ iOS, macOS.

委托定制

轻量级定制

每个手势识别器都有一个默认的 RxGestureRecognizerDelegate。它允许您使用策略自定义每个委托方法

以下是可用的策略及其对应的委托方法

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

可以在配置闭包中自定义此委托

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
  }
})

可以在 RxGestureRecognizerDelegate.swift 中找到默认值。

完整定制

您还可以用您自己的委托替换默认委托,或者将其删除。

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

要求

此库依赖于 RxSwiftRxCocoa

安装

CocoaPods

添加到 Podfile

pod "RxGesture"
$ pod install

Carthage

添加到 Cartfile

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

感谢

RxSwift Slack 频道中的每个人 💯

许可证

RxGesture 在 MIT 许可下可用。 有关更多信息,请参见 LICENSE 文件。