'How to pass argument or return value from a function placed in view model and called in xml using data binding

I have been trying to pass some argument and get a boolean as a return for a function placed in view model class and calling that function in xml using data binding.

View model:

class ChatViewModel: ViewModel() {

    val latestMessageFromFirst = MutableLiveData<String>()
    private val emailOfUser = MutableLiveData<String>()
    val isEmailValid = MutableLiveData<Boolean>()

    fun setEmailOfUser(email: String) {
        emailOfUser.value = email
    }

    fun setLatestMessageFromFirst(data: String) {
        latestMessageFromFirst.value = data
    }

    fun verifyEmailAddress() {
        emailOfUser.value?.let { email ->
            isEmailValid.value = email.isNotEmpty() && Patterns.EMAIL_ADDRESS.matcher(email).matches()
        }
    }
}

XML:

<androidx.appcompat.widget.AppCompatButton
            android:id="@+id/btnVerifyEmail"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/_30sdp"
            android:background="@drawable/stroke_button"
            android:text="@string/verify"
            android:onClick="@{() -> viewModel.verifyEmailAddress()}"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/etEmailOfUser"
            app:layout_constraintWidth_percent="0.3" />

Fragment:

class UserTwoFragment : Fragment() {

    private lateinit var binding: FragmentUserTwoBinding
    private val viewModel: ChatViewModel by activityViewModels()

    override fun onResume() {
        binding.viewModel = viewModel
        super.onResume()
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = DataBindingUtil.inflate(inflater, R.layout.fragment_user_two, container, false)
        binding.viewModel = viewModel
        binding.lifecycleOwner = this
        val view = binding.root

        binding.etEmailOfUser.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {  }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                var email = ""
                s?.let {
                    email = it.toString()
                }
                viewModel.setEmailOfUser(email)
                viewModel.isEmailValid.observe(viewLifecycleOwner) {
                    binding.tvIsEmailValid.text = if (it) {
                        getString(R.string.valid_email_text)
                    } else {
                        getString(R.string.invalid_email_text)
                    }
                }
                binding.viewModel = viewModel
            }

            override fun afterTextChanged(s: Editable?) {  }
        })


        return view
    }
}

Can anyone suggest how can I achieve the result of the function(called in xml) in my fragment(activity if not using fragments)?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source