如何使用RxSwift检测双击

问题描述 投票:0回答:3

我正在尝试使用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知道第二个必须失败?

ios swift rx-swift rx-cocoa
3个回答
0
投票

您可以使用RxGesture(https://github.com/RxSwiftCommunity/RxGesture)。

并且用法就像您写的一样:

clapButton.rx.
    .tapGesture(numberOfTapsRequired: 2)
    .when(.recognized)
    .subscribe(onNext: {
    // toggle the light
})

0
投票

我已经找到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
    }
}

两种解决方案都可以正常工作。


0
投票

此代码应该起作用:

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毫秒)内输出连续抽头的数量。该映射只是为了确保仅出现12。然后使用您喜欢的任何条件逻辑。我成功地用UIButton对其进行了测试。

© www.soinside.com 2019 - 2024. All rights reserved.