我有一个文本字段需要验证,我想在用户键入时禁用按钮。用户停止输入后(1 秒去抖),将执行验证并根据结果有条件地启用按钮。请注意当用户仅键入一个字符时的极端情况,验证仍然应该发生。
--"a"-"ab"-"abc"------------------"ab"--"a"------------------"ab"-----------------
--false---------validate("abc")---false----validate("a")-----false--validate("ab")
这个所以(立即交付第一个项目,“消除”后续项目 https://stackoverflow.com/questions/30140044/deliver-the-first-item-immediately-debounce-following-items)在RxJava中提出了以下解决方案。但它似乎只返回第一个元素,而不是当用户在去抖后再次开始输入时返回?如果我错了请纠正我
Observable.from(items).publish(publishedItems ->
publishedItems.limit(1).concatWith(
publishedItems.skip(1).debounce(1, TimeUnit.SECONDS)
)
)
一种选择是将问题“用户是否正在键入”与“输入是否有效”分开。
描述用户是否正在打字的一种(有点笨拙)方式:
let isTyping = PublishSubject<Bool>()
textField.rx.text
.map { _ in true }
.bind(to: isTyping)
.disposed(by: disposeBag)
textField.rx.text
.debounce(1.0, scheduler: MainScheduler.instance)
.map { _ in false}
.bind(to: isTyping)
.disposed(by: disposeBag)
然后,您可以像这样描述按钮启用状态:
isTyping.withLatestFrom(isValid) { !$0 && $1 }
.bind(to: button.rx.isEnabled)
当然,为了让这种方法在用户开始输入时立即生效,最好isValid
从一个值开始。
您还可以通过以下方式简化它。如果这些值仅在本地使用,这可能没问题。
textField.rx.text
.map { _ in false }
.bind(to: button.rx.isEnabled)
.disposed(by: disposeBag)
textField.rx.text
.debounce(1.0, scheduler: MainScheduler.instance)
.flatMap { [weak self] in self?.validate($0) }
.bind(to: button.rx.isEnabled)
.disposed(by: disposeBag)
请注意,使用这种方法,当用户恢复输入时,需要取消异步验证操作。
希望有人可以提出一个更清洁的解决方案,但我认为这是一个不错的起点。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)