0

I'm still new to all this MVVM and Android Architecture Components. I have a few screens (Login and Register) that have inputs for email, password, name etc and a 'continue' button that's only enabled when the required fields are filled out correctly. There's also text views for messages such as "password must be..." and "not a valid email...". I'm trying to use a binding adapter and viewmodel to pull some of this validation logic out of my MainActivity and away from my business logic, but I'm struggling. I'm not even sure if this is the best way to do it. My thought with the ViewModel is that it would hold it's state on rotation/activity changes.

RegisterActivity is an Activity that simply holds a ViewPager with 3 fragments (email/password, first/last name, validation code).

Binding Adapter

@BindingAdapter("app:onTextChanged")
public static void onTextChanged(TextInputEditText view, TextViewBindingAdapter.OnTextChanged listener) {

}

Layout

<TextView
            android:id="@+id/tv_error_message"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:text="@string/register_email_requirement"
            android:textColor="@color/moenPrimaryError"
            android:textSize="18sp"
            android:visibility="@{viewModel.emailValidationVisible ? View.VISIBLE: View.GONE}"
            app:layout_constraintBottom_toTopOf="@id/input_layout_password"
            app:layout_constraintEnd_toEndOf="@+id/input_layout_email_address"
            app:layout_constraintStart_toStartOf="@+id/input_layout_email_address"
            app:layout_constraintTop_toBottomOf="@+id/input_layout_email_address"
            app:layout_goneMarginTop="16dp" />

<com.google.android.material.textfield.TextInputEditText
                android:id="@+id/input_email_address"
                style="@style/MoenTextInputEditText"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="textEmailAddress"
                app:onTextChanged="@{viewModel.onTextChanged}"
                app:onFocusChange="@{inputLayoutEmailAddress}">

            </com.google.android.material.textfield.TextInputEditText>

ViewModel

public class RegisterFragmentViewModel extends BaseObservable {
    private boolean emailValidationVisible = false;

    @Bindable
    public boolean getEmailValidationVisible() {
        return this.emailValidationVisible;
    }

    public void toggle() {
        this.emailValidationVisible = !this.emailValidationVisible;
        notifyPropertyChanged(BR.viewModel);
    }

    public void onTextChanged(CharSequence s, int start, int before, int count) {
        Log.w("tag", "onTextChanged " + s);
        this.toggle();
    }
}

This is just a test I have. My thought was that I could bind the TextView visibility to a boolean that I can toggle/manipulate with a onTextChanged listener, but I don't know how to wire up the Binding Adapter. Am I on the right path? Is there a better/easier way to do this?

Nelson.b.austin
  • 3,080
  • 6
  • 37
  • 63

1 Answers1

0

Am I on the right path? Is there a better/easier way to do this?

it is a way of doing it. I would remove the ternary operator from this line

  android:visibility="@{viewModel.emailValidationVisible ? View.VISIBLE: View.GONE}"

and create a simple function in your VM that returns it. EG:

   @Bindable
   public int getVisibility() {
      return emailValidationVisible ? View.VISIBLE: View.GONE     
   }

and in toggle(), you will have something like

 public void toggle() {
    this.emailValidationVisible = !this.emailValidationVisible;
    notifyPropertyChanged(BR.visibility);
}

which will call the getter for you. Your xml will have to be changed like follow

  android:visibility="@{viewModel.getVisibility()}"

Alternately you could create a BindingAdapter that takes a Boolean and change the visibility accordingly to it

Blackbelt
  • 156,034
  • 29
  • 297
  • 305