1

让我为一项需要我花费数天时间才能弄清楚的小任务动脑筋……

我有一个 EditText,用户将输入一个字符串,该字符串将用于进行 Wikipedia 搜索并将结果提供给 ListView。EditText 应该有 1 秒的限制,并且必须进行过滤才能检查“不适当”字符串列表。如果输入在该字符串列表中,则搜索将不会通过,除非用户同时触摸在屏幕的 2 个角上找到的 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));

其中 isInappropriate(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 时才会发出......

如果您有任何提示或实际解决方案,请随时发表评论。谢谢。

4

2 回答 2

1

这还不够吗?

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),
        RxTextView.textChanges(etxtSearchFilter)
                .debounce(1, TimeUnit.SECONDS)
                .map(c -> c.toString().trim())
                .filter(s -> !s.isEmpty()),
        (motionEventLeft, motionEventRight, entered) -> {
            boolean overrideFilter = motionEventLeft.getAction() == MotionEvent.ACTION_DOWN && motionEventRight.getAction() == MotionEvent.ACTION_DOWN;
            return overrideFilter || !isInappropriate(entered) ? entered : "BLOCKED";
        })
        .subscribe(s -> Log.i("ObservableCombineLatest", "s: " + s));

(我也改成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));
于 2016-07-08T08:11:55.337 回答
1

你似乎走在正确的轨道上,但你可能想用startsWithie “初始化”你的隐藏视图

// 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);
于 2016-07-08T08:29:46.397 回答