========= 2017.05.31 수정 ========
https://stackoverflow.com/a/33474455/1025379 의 방법으로 변경했음.
정보를 입력하는 화면에서 제대로 입력하지 않았을 때도 MVVM으로 할 수 있다. 이런 작업은 RxBindig을 사용했는데, MVVM과 RxJava를 같이 사용하는 글을 따라하다가 문득 생각나서 찾아보니 RxBinding 이 RxJava 2를 지원하게 바뀌어서 혹시나 싶어서 RxJava 2로 바꾸다가 실패해서 다른 방법을 찾았다. 이게 더 쉬운 것 같다.
이 방법은 보통은 2-way data bingding 같은 걸로 많이 검색되더라.
이름, 이메일, 점수를 모두 입력해야하고, 이메일은 이메일 규칙에 맞아야만 버튼이 활성화 되게 만들었다.
사용할 뷰모델을 만든다.
public class InputViewModel implements BaseViewModel { public final ObservableField<String> name = new ObservableField<>(); public final ObservableField<String> email = new ObservableField<>(); public final ObservableInt score = new ObservableInt(); public final ObservableBoolean isValid = new ObservableBoolean(); @Override public void onCreate() { score.set(0); isValid.set(false); name.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { validation(); } }); email.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { validation(); } }); } @Override public void onResume() {} @Override public void onPause() {} @Override public void onDestroy() {} private void validation() { boolean isValidName = !TextUtils.isEmpty(name.get()); boolean isValidEmail = !TextUtils.isEmpty(email.get()) && Patterns.EMAIL_ADDRESS.matcher(email.get()).matches(); boolean isValidScore = score.get() > 0; isValid.set(isValidName && isValidEmail && isValidScore); } public RatingBar.OnRatingBarChangeListener scoreChangeListener = new RatingBar.OnRatingBarChangeListener() { @Override public void onRatingChanged(RatingBar ratingBar, float v, boolean b) { score.set((int) v); validation(); } }; }
화면도 만든다.
<?xml version="1.0" encoding="utf-8"?> <layout> <data> <variable name="model" type="kr.susemi99.testmvvm.view_models.InputViewModel"/> </data> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical"> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="name" android:text="@={model.name}"/> <!-- not @{model.name} --> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="email" android:inputType="textEmailAddress" android:text="@={model.email}"/> <!-- not @{model.email} --> <RatingBar android:layout_width="wrap_content" android:layout_height="wrap_content" android:rating="@{model.score}" android:stepSize="1" app:OnRatingBarChangeListener="@{model.scoreChangeListener}"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:enabled="@{model.isValid}" android:text="@android:string/ok"/> </LinearLayout> </layout>
뷰모델을 연결시켜주면 끝난다.
public class InputActivity extends AppCompatActivity { private InputViewModel model = new InputViewModel(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActivityInputBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_input); binding.setModel(model); model.onCreate(); } }
아무 것도 입력하지 않으면 ok 버튼은 비활성화 된다.
이름과 이메일을 넣어도 점수를 넣지 않으면 비활성화 된다.
다 넣었지만, 이메일 규격이 맞지 않으면 역시 비활성화 된다.
모두 입력하고, 이메일 규격에도 맞으면 활성화 된다.
RxBinding과 ButterKnife 를 안 써도 이렇게 쉽게 할 수 있다.