RxAndroid:观察EditText,同时观察2个视图上的触摸

时间:2016-07-08 06:24:32

标签: java android rx-java rx-android reactivex

让我挑选一个关于一项小任务的大脑,这项任务花了我几天的时间才弄明白......

我有一个EditText,用户将输入一个String,用于进行维基百科搜索并提供带有结果的ListView。 EditText应该有1秒的限制,并且必须进行过滤才能检查“不合适”的列表。字符串。如果输入在String列表中,搜索将不会通过,除非用户同时触摸屏幕两个角上的2个隐藏视图,否则它将跳过此检查。

这里有一些片段可以帮助您了解我已经拥有的内容......

// a list of inappropriate content
private static String[] INAPPROPRIATE_CONTENT = {
            "test"
        };

// subscription to the touches happening on hidden view #1
Subscription subSecretLeft = RxView.touches(vSecretLeft)
        .filter(motionEvent -> motionEvent.getAction() == MotionEvent.ACTION_DOWN || motionEvent.getAction() == MotionEvent.ACTION_UP)
        .subscribe(motionEvent -> secretLeftClicked = motionEvent.getAction() == MotionEvent.ACTION_DOWN);

// subscription to the touches happening on hidden view #2
RxView.touches(vSecretRight)
        .filter(motionEvent -> motionEvent.getAction() == MotionEvent.ACTION_DOWN || motionEvent.getAction() == MotionEvent.ACTION_UP)
        .subscribe(motionEvent -> secretRightClicked = motionEvent.getAction() == MotionEvent.ACTION_DOWN);

// subscription to the EditText
RxTextView.textChanges(etxtSearchFilter)
        .throttleLast(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
        .map(c -> c.toString().trim())
        .filter(s -> !(s.isEmpty() || isInappropriate(s)))
        .subscribe(s -> fetchWikiSearch(s));

WhereInappropriate(String s)是检查数组中是否找到该术语的方法,fetchWikiSearch(String s)执行搜索并填充ListView。

我尝试了几种方法,我可以提出的最后一种方法如下:

Observable.zip(
        Observable.combineLatest(
                RxView.touches(vSecretLeft)
                        .filter(motionEvent -> motionEvent.getAction() == MotionEvent.ACTION_DOWN || motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL),
                RxView.touches(vSecretRight)
                        .filter(motionEvent -> motionEvent.getAction() == MotionEvent.ACTION_DOWN || motionEvent.getAction() == MotionEvent.ACTION_UP || motionEvent.getAction() == MotionEvent.ACTION_CANCEL),
                (ev1, ev2) -> ev1.getAction() == MotionEvent.ACTION_DOWN && ev2.getAction() == MotionEvent.ACTION_DOWN
        ).asObservable(),
        RxTextView.textChanges(etxtSearchFilter)
                .throttleLast(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread())
                .map(c -> c.toString().trim())
                .filter(s -> !s.isEmpty()),
        (overrideFilter, s) ->
                overrideFilter || !isInappropriate(s) ? s : "BLOCKED"
).subscribe(s -> Log.i("ObservableZip", "s: " + s));

但显然,只要我不触及这些观点,它就不会发出任何东西。即使是Observable.combileLatest()也不是很好用,因为它只有在两个视图都获得MotionEvent.ACTION_DOWN时才会发出......

如果您有任何提示或实际解决方案,请不要犹豫,发表评论。感谢。

2 个答案:

答案 0 :(得分:1)

那不够吗?

throttleLast

(我也将debounce更改为Observable.combineLatest( RxView.touches(vSecretLeft) .map(motionEvent -> motionEvent.getAction()) .filter(action -> action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) .startWith(MotionEvent.ACTION_UP), RxView.touches(vSecretRight) .map(motionEvent -> motionEvent.getAction()) .filter(action -> action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) .startWith(MotionEvent.ACTION_UP), RxTextView.textChanges(etxtSearchFilter) .debounce(1, TimeUnit.SECONDS) .map(c -> c.toString().trim()) .filter(s -> !s.isEmpty()), (leftAction, rightAction, entered) -> { boolean overrideFilter = leftAction == MotionEvent.ACTION_DOWN && rightAction == MotionEvent.ACTION_DOWN; return overrideFilter || !isInappropriate(entered) ? entered : "BLOCKED"; }) .subscribe(s -> Log.i("ObservableCombineLatest", "s: " + s)); ,因为它在某种程度上感觉更好用于此目的)

修改

{{1}}

答案 1 :(得分:1)

您似乎走在正确的轨道上,但您可能希望用startsWith“初始化”隐藏的视图,即

// subscription to the touches happening on hidden view #1
Subscription subSecretLeft = RxView.touches(vSecretLeft)
        .filter(motionEvent -> motionEvent.getAction() == MotionEvent.ACTION_DOWN || motionEvent.getAction() == MotionEvent.ACTION_UP)
        .startsWith(MotionEvent.ACTION_UP)
        .subscribe(motionEvent -> secretLeftClicked = motionEvent.getAction() == MotionEvent.ACTION_DOWN);