RxJava / RxAndroid - 处理多个EditText更改

时间:2015-08-28 05:18:21

标签: java android reactive-programming rx-java rx-android

我有3个EditText字段,我为这些字段创建了3个observable。

    Observable<CharSequence> o1 = RxTextView.textChanges(field1);
    Observable<CharSequence> o2 = RxTextView.textChanges(field2);
    Observable<CharSequence> o3 = RxTextView.textChanges(field3);

我希望在所有这三个字段都有一些值时启用按钮。用户可以在字段中以任何顺序输入值。我怎么能这样做?

修改

我用zip实现了这个目标。

Observable<CharSequence> o1 = RxTextView.textChanges(field1);
Observable<CharSequence> o2 = RxTextView.textChanges(field2);
Observable<CharSequence> o3 = RxTextView.textChanges(field3);
Observable.zip(o1, o2, o3, (c1, c2, c3) -> c1.length() > 0 && c2.length() > 0 && c3.length() > 0).subscribe(myButton::setEnabled)

当我在所有三个文本字段中输入内容时,上述情况有效。例如我在所有三个文本字段中输入了1个字符,然后按钮将被启用。但是当我删除三个字段中的任何一个字符时。 zip不会被调用,因为它会在订阅者调用onNext之前等待其他两个文本字段流式传输某些数据。所以当我删除任何文本字段中的任何字符时,我希望我的按钮再次被禁用。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:9)

使用 numbers=["7", "4", "1", "8", "5", "2", "9", "6", "3"] for i in range(9): n=numbers[i] Button(buttons, bg="snow", text=n, width=7, height=1, command=show_up(n), relief=RAISED).grid(row=i%3, column=i//3) Clear = Button(buttons, bg="snow", text="C", width=7, height=1, command=self.clear, relief=RAISED) Clear.grid(padx=2, pady=2, column=3, row=0) Equals = Button(buttons, bg="snow", text="=", width=7, height=1, command=self.equals, relief=RAISED) Equals.grid(padx=2, pady=2, column=4, row=3) All_clear = Button(buttons, bg="snow", text="AC", width=7, height=1, command=self.all_clear, relief=RAISED) All_clear.grid(padx=2, pady=2, column=4, row=0) Bracket_one = Button(buttons, bg="snow", text="(", width=7, height=1, command=self.bracket_one, relief=RAISED) Bracket_one.grid(padx=2, pady=2, column=2, row=3) Bracket_two = Button(buttons, bg="snow", text=")", width=7, height=1, command=self.bracket_two, relief=RAISED) Bracket_two.grid(padx=2, pady=2, column=3, row=3) Zero = Button(buttons, bg="snow", text="0", width=7, height=1, command=self.zero, relief=RAISED) Zero.grid(padx=2, pady=2, column=0, row=3) Decimal_point = Button(buttons, bg="snow", text=".", width=7, height=1, command=self.decimal_point, relief=RAISED) Decimal_point.grid(padx=2, pady=2, column=1, row=3) Multiplication = Button(buttons, bg="red", text="x", width=7, height=1, command=self.multiplication, relief=RAISED) Multiplication.grid(padx=2, pady=2, column=3, row=1) Division = Button(buttons, bg="powder blue", text="/", width=7, height=1, command=self.division, relief=RAISED) Division.grid(padx=2, pady=2, column=4, row=1) Addition = Button(buttons, bg="yellow", text="+", width=7, height=1, command=self.addition, relief=RAISED) Addition.grid(padx=2, pady=2, column=3, row=2) Subtraction = Button(buttons, bg="green", text="-", width=7, height=1, command=self.subtraction, relief=RAISED) Subtraction.grid(padx=2, pady=2, column=4, row=2) def equals(self): try: result = eval(self.results.get()) except: result = "Error" self.all_clear() self.results.insert(0, result) def zero(self): self.results.insert(END, "0") def bracket_one(self): self.results.insert(END, "(") def bracket_two(self): self.results.insert(END, ")") def all_clear(self): self.results.delete(0, END) def clear(self): self.results.delete(-1) def multiplication(self): self.results.insert(END, "*") def division(self): self.results.insert(END, "/") def addition(self): self.results.insert(END, "+") def subtraction(self): self.results.insert(END, "-") def decimal_point(self): self.results.insert(END, ".") 代替CombineLatest http://reactivex.io/documentation/operators/combinelatest.html

答案 1 :(得分:4)

试试这个,这肯定会起作用。 使用combineLatest。

//declare global variable
 private Subscription subscription = null;
 Observable<CharSequence> o1 = RxTextView.textChanges(field1);
 Observable<CharSequence> o2 = RxTextView.textChanges(field2);

 public void combineEvent(){
 subscription = Observable.combineLatest(o1, o2,
    new Func2<CharSequence, CharSequence, Boolean>() {
      @Override public Boolean call(CharSequence newEmail, CharSequence  newPassword) {
    //here you can validate the edit text
      boolean emailValid= !TextUtils.isEmpty(newEmail)
          &&    android.util.Patterns.EMAIL_ADDRESS.matcher(newEmail).matches();
        if(!emailValid){
          etEmailAddress.setError("Invalid Email");
        }
        boolean passValid = !TextUtils.isEmpty(newPassword)
            && newPassword.length() >6;
        if(!passValid){
          etPassword.setError("invalid password");
        }


        return emailValid && passValid;

      }
      }).subscribe(new Observer<Boolean>() {
    @Override public void onCompleted() {

    }

    @Override public void onError(Throwable e) {

  }

  @Override public void onNext(Boolean aBoolean) {
    if(aBoolean){
      //here you can enable your button or what ever you want.
      loginBtn.setEnabled(true);

    }else {
      loginBtn.setEnabled(false);
    }

  }
});
}