如何使用 RxSwift 检测双击
Posted
技术标签:
【中文标题】如何使用 RxSwift 检测双击【英文标题】:How to detect double tap with RxSwift 【发布时间】:2020-02-11 12:32:21 【问题描述】:我正在尝试使用 RxSwift 检测双击
如果没有 RxSwift,我会是这样的:
private func setupFakePanView()
let singleTapGesture = UITapGestureRecognizer()
let doubleTapGesture = UITapGestureRecognizer()
singleTapGesture.numberOfTapsRequired = 1
doubleTapGesture.numberOfTapsRequired = 2
singleTapGesture.addTarget(self, action: #selector(self.tapped))
doubleTapGesture.addTarget(self, action: #selector(self.doubleTapped))
someView.addGestureRecognizer(singleTapGesture)
someView.addGestureRecognizer(doubleTapGesture)
singleTapGesture.require(toFail: doubleTapGesture)
@objc private func tapped()
// Do something
@objc private func doubleTapped()
// Do something else
有没有办法让 RxSwift、RxCocoa 和 RxGesture 达到同样的效果?我尝试了以下方法,但它当然不起作用:
someView.rx
.tapGesture(numberOfTouchesRequired: 1, numberOfTapsRequired: 1)
.when(.recognized)
.subscribe(onNext: _ in
// Do something
)
.disposed(by: bag)
someView.rx
.tapGesture(numberOfTouchesRequired: 1, numberOfTapsRequired: 2)
.when(.recognized)
.subscribe(onNext: _ in
// Do something else
)
.disposed(by: bag)
有没有办法让第一个 tapGesture 知道第二个必须失败?
【问题讨论】:
您可以为单击手势设置委托,然后使用shouldRequireFailureOf
方法
您是否正在为这些额外的运算符使用库?如果是这样,那是什么?如果不是,那么它们的实现是什么?
设置委托不起作用,在这种情况下你将如何实现shouldRequireFailureOf
。您也需要其他手势,对吗? @KishanBhatiya
是的,哦应该加上:RxGesture。 @DanielT。
也许这有帮助:github.com/RxSwiftCommunity/RxGesture/issues/46
【参考方案1】:
我找到了 2 个解决方案来解决这个问题!
A.使用自定义UITapGestureRecognizer
let doubleTapGesture = UITapGestureRecognizer()
doubleTapGesture.numberOfTapsRequired = 2
let singleTapGesture = UITapGestureRecognizer()
singleTapGesture.numberOfTapsRequired = 1
singleTapGesture.require(toFail: doubleTapGesture)
let singleTap = someView.rx
.gesture(singleTapGesture)
.when(.recognized)
.subscribe(onNext: _ in
// Do something
)
.disposed(by: bag)
let doubleTap = someView.rx
.gesture(doubleTapGesture)
.when(.recognized)
.subscribe(onNext: _ in
// Do something else
)
.disposed(by: bag)
或者..
B.使用自定义UIGestureRecognizerDelegate
感谢Kishan 建议Jegnux's answer!
1 - 为单击手势设置自定义委托...
someView.rx
.tapGesture(
numberOfTouchesRequired: 1,
numberOfTapsRequired: 1,
configuration: [weak self] gesture, delegate in
gesture.delegate = self
)
.subscribe(onNext: _ in
// Do something
)
.disposed(by: bag)
// double tap same as before
2 - 实现gestureRecognizer(_:shouldRequireFailureOf:)
extension MyController: UIGestureRecognizerDelegate
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool
if let gesture = otherGestureRecognizer as? UITapGestureRecognizer, gesture.numberOfTapsRequired == 2
return true
return false
两种解决方案都可以正常工作。
【讨论】:
【参考方案2】:这段代码应该可以工作:
tap
.flatMapFirst
tap
.takeUntil(tap.startWith(()).debounce(.milliseconds(300), scheduler: MainScheduler.instance))
.startWith(())
.reduce(0) acc, _ in acc + 1
.map min($0, 2)
只需使用一个手势识别器(其事件称为tap
),它会在点击发生时立即发出。 map
上面的代码将这个问题概括为在这种情况下输出彼此在一定周期(300 ms)内的连续抽头数。该地图只是为了确保只有1
或2
出来。然后用它做任何你喜欢的条件逻辑。我用UIButton
测试成功。
【讨论】:
所有这些运算符的有趣用法! @Tieme Dank je wel!tap
必须是一个共享的 observable 才能工作以上是关于如何使用 RxSwift 检测双击的主要内容,如果未能解决你的问题,请参考以下文章
Qt:使用 Modkey(Shift、CTRL 等)检测双击