{"id":357773,"date":"2024-05-20T23:57:50","date_gmt":"2024-05-20T23:57:50","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=357773"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=357773","title":{"rendered":"<span>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0440\u0430\u043d\u043e\u0432 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Custom View \u0438 Firebase<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438 \u0425\u0430\u0431\u0440!<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0430\u0441 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a. \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0441\u0442\u043e\u0438\u0442 \u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c View \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0432\u0435\u0434\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0431\u044b\u043b\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u0435\u0434\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0432\u043e\u0435\u0433\u043e email \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u0442 \u043f\u0430\u0440\u043e\u043b\u044c \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0446\u0438\u0444\u0440\u044b? \u0412 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u044d\u0442\u043e \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e! \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Custom View \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 firebase.<\/p>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0414\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438 \u0438 \u0442\u0440\u0438 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u2013 \u044d\u043a\u0440\u0430\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u2013 \u044d\u043a\u0440\u0430\u043d \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0435\u0441\u043b\u0438 \u043e\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0448\u0435\u043b \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432. \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u043a\u0430\u043a \u044f \u043f\u0438\u0441\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 firebase.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f   <\/h2>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 Custom View \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0438 \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0442\u0430\u043a\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0431\u0443\u0434\u0435\u0442 CustomInputLayout.<\/p>\n<pre><code class=\"kotlin\">abstract class CustomInputLayout @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : TextInputLayout(context, attrs, defStyleAttr), Validation {      protected abstract val errorMessageId: Int     private val textWatcher = RegistrationTextWatcher { error = \"\" }      open fun text() = editText?.text.toString()      override fun onAttachedToWindow() {         super.onAttachedToWindow()         editText?.addTextChangedListener(textWatcher)     }      override fun isValid(): Boolean {         val isValid = innerIsValid()         error = if (isValid) \"\" else context.getString(errorMessageId)         return isValid     }      protected abstract fun innerIsValid(): Boolean }  interface Validation {     fun isValid(): Boolean }<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 CustomInputLayout, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430 TextInputLayout \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Android Material Design. CustomInputLayout \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Validation.<\/p>\n<p>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b context, attrs \u0438 defStyleAttr, \u0433\u0434\u0435 context \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, attrs \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435, \u0430 defStyleAttr &#8212; \u0441\u0442\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d \u043a \u043c\u0430\u043a\u0435\u0442\u0443.<\/p>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0447\u043b\u0435\u043d\u044b:<\/p>\n<ol>\n<li>\n<p>errorMessageId &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>textWatcher &#8212; \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 RegistrationTextWatcher \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>text() &#8212; \u00a0\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u0437 \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>onAttachedToWindow() &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 textWatcher \u043a \u043f\u043e\u043b\u044e \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>isValid() &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Validation, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 true, \u0435\u0441\u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c, \u0438 false &#8212; \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<\/li>\n<li>\n<p>innerIsValid() &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043b\u0430\u0441\u0441\u0430\u0445-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 RegistrationTextWatcher, \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0432 CustomInputLayout.<\/p>\n<pre><code class=\"kotlin\">class RegistrationTextWatcher(private val onTextChanged: () -> Unit) : TextWatcher {      override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {     }      override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {         onTextChanged.invoke()     }      override fun afterTextChanged(s: Editable?) {     } }<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 RegistrationTextWatcher \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044e onTextChanged, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430. \u042d\u0442\u043e \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 (Unit).<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043a\u043b\u0430\u0441\u0441 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0440\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 TextWatcher:<\/p>\n<ol>\n<li>\n<p>beforeTextChanged &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043c\u0435\u0442\u043e\u0434 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u0443\u0441\u0442\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>onTextChanged &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f onTextChanged.invoke(), \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 onTextChanged, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0439 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043a\u043b\u0430\u0441\u0441\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>afterTextChanged &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430. <\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u043b\u0430\u0441\u0441 RegistrationTextWatcher \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043f\u043e\u043b\u0435 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e onTextChanged, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u044d\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u043a\u043b\u0430\u0441\u0441, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u043b\u0435\u0439 Email \u0438 Password, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"kotlin\">class MailInput @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : CustomInputLayout(context, attrs, defStyleAttr) {     override val errorMessageId = R.string.login_error      override fun innerIsValid(): Boolean {         return Patterns.EMAIL_ADDRESS.matcher(text()).matches()     } }<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u043a\u043b\u0430\u0441\u0441 MailInput, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u043d\u0435\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 CustomInputLayout. \u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b.<\/p>\n<p>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 MailInput \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>context: Context &#8212; \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>attrs: AttributeSet &#8212; \u043d\u0430\u0431\u043e\u0440 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 XML-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>defStyleAttr: Int &#8212; \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u0442\u0438\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<p>@JvmOverloads &#8212; \u044d\u0442\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0438\u0437 Java-\u043a\u043e\u0434\u0430.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 MailInput \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ol>\n<li>\n<p>innerIsValid() &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u043f\u043e\u043b\u0435 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c. <\/p>\n<\/li>\n<li>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 Java Patterns.EMAIL_ADDRESS.matcher(text()).matches(), \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b. \u0415\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0443, \u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; false.<\/p>\n<\/li>\n<li>\n<p>errorMessageId &#8212; \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 R.string.login_error. \u042d\u0442\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u0435\u0441\u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">class PasswordInput @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : CustomInputLayout(context, attrs, defStyleAttr) {      override val errorMessageId: Int = R.string.password_error      override fun innerIsValid(): Boolean {         return text().matches(Regex(PASSWORD_PATTERN))     }      companion object {          private const val PASSWORD_PATTERN =             \"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@\\$%^&amp;*-]).{8,}\\$\"     } }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043c\u0430\u043b\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u0439 <\/p>\n<p>errorMessageId \u2013 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 R.string.password_error.<\/p>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 PASSWORD_PATTERN, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u0430\u043a EMAIL_ADDRESS, \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d.<\/p>\n<p>\u0414\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0431\u0443\u043a\u0432\u0443 [A-Z].<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u043e\u0447\u043d\u0443\u044e \u0431\u0443\u043a\u0432\u0443 [a-z].<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0446\u0438\u0444\u0440\u0443 [0-9].<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0438\u043c\u0432\u043e\u043b [#?!@\\$%^&amp;*-].<\/p>\n<\/li>\n<li>\n<p>\u0418\u043c\u0435\u044e\u0442 \u0434\u043b\u0438\u043d\u0443 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 8 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 .{8,}.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0435 \u0441 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043a\u0440\u043e\u043c\u0435 \u043f\u043e\u043b\u044f \u0441 email \u0431\u0443\u0434\u0443\u0442 \u0434\u0432\u0430 \u043f\u043e\u043b\u044f password \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u0435\u0439.<\/p>\n<pre><code class=\"kotlin\">class PasswordLayout @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr), Validation {      private val binding = PasswordLayoutBinding.inflate(LayoutInflater.from(context), this)      init {         orientation = VERTICAL         listOf(binding.passwordEditText, binding.passwordRepeatEditText).forEach {             it.addTextChangedListener(RegistrationTextWatcher {                 binding.errorText.text = \"\"             })         }     }      private val errorMessageId: Int = R.string.password_error_same      override fun isValid(): Boolean {         with(binding) {             val isPasswordsEquals = passwordLayout.text() == passwordRepeatLayout.text()             errorText.text = if (isPasswordsEquals) \"\" else context.getString(errorMessageId)             val isPasswordsValid = listOf(passwordLayout, passwordRepeatLayout).map { it.isValid() }             return isPasswordsValid.all { it } &amp;&amp; isPasswordsEquals         }     }      fun text(): String {         return binding.passwordLayout.text()     } }<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 PasswordLayout \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e binding, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043d\u0444\u043b\u0435\u0439\u0442\u0438\u0442 \u043c\u0430\u043a\u0435\u0442 PasswordLayoutBinding \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c LayoutInflater \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443 LinearLayout.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u0432 \u0431\u043b\u043e\u043a\u0435 init \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u043c\u0430\u043a\u0435\u0442\u0430, \u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f (passwordEditText \u0438 passwordRepeatEditText) \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f TextChangedListener, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u0430\u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 RegistrationTextWatcher. \u042d\u0442\u043e\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u043b\u044f\u0445 \u0432\u0432\u043e\u0434\u0430 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 (errorText) \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f errorMessageId \u0445\u0440\u0430\u043d\u0438\u0442 R.string.password_error_same, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0438, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 isValid() \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Validation \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044f \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f passwordLayout \u0438 passwordRepeatLayout \u0432 \u043c\u0430\u043a\u0435\u0442\u0435 \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 errorText \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f. \u0417\u0430\u0442\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 true, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u0438 false \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 text() \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0438\u0437 \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f passwordLayout \u0432 \u043c\u0430\u043a\u0435\u0442\u0435, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u044f\u0445 \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0440\u0441\u0442\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u044d\u043a\u0440\u0430\u043d\u043e\u0432.<\/p>\n<p>\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430 MainActivity.<\/p>\n<pre><code class=\"xml\">&lt;androidx.constraintlayout.widget.ConstraintLayout 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\"     tools:context=\".core.ui.MainActivity\">      &lt;androidx.fragment.app.FragmentContainerView         android:id=\"@+id\/nav_host_fragment\"         android:name=\"androidx.navigation.fragment.NavHostFragment\"         android:layout_width=\"match_parent\"         android:layout_height=\"match_parent\"         app:defaultNavHost=\"true\"         app:layout_constraintBottom_toBottomOf=\"parent\"         app:layout_constraintEnd_toEndOf=\"parent\"         app:layout_constraintStart_toStartOf=\"parent\"         app:layout_constraintTop_toTopOf=\"parent\"         app:navGraph=\"@navigation\/nav_graph\" \/>  &lt;\/androidx.constraintlayout.widget.ConstraintLayout><\/code><\/pre>\n<p>\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430 AuthorizationFragment.<\/p>\n<pre><code class=\"xml\">&lt;androidx.constraintlayout.widget.ConstraintLayout 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\"     tools:context=\".features.ui.authorization.AuthorizationFragment\">      &lt;ru.anb.passwordapp.features.ui.input.PasswordInput         android:id=\"@+id\/auth_password\"         style=\"@style\/Widget.Material3.TextInputLayout.OutlinedBox\"         android:layout_width=\"match_parent\"         android:layout_height=\"wrap_content\"         android:layout_marginHorizontal=\"16dp\"         android:layout_marginTop=\"32dp\"         android:hint=\"@string\/password\"         app:endIconDrawable=\"@drawable\/eye\"         app:endIconMode=\"password_toggle\"         app:layout_constraintEnd_toEndOf=\"parent\"         app:layout_constraintStart_toStartOf=\"parent\"         app:layout_constraintTop_toBottomOf=\"@+id\/auth_mail\">          &lt;com.google.android.material.textfield.TextInputEditText             android:id=\"@+id\/password_edittext\"             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:inputType=\"textPassword\" \/>      &lt;\/ru.anb.passwordapp.features.ui.input.PasswordInput>      &lt;ru.anb.passwordapp.features.ui.input.MailInput         android:id=\"@+id\/auth_mail\"         style=\"@style\/Widget.Material3.TextInputLayout.OutlinedBox\"         android:layout_width=\"match_parent\"         android:layout_height=\"wrap_content\"         android:layout_marginHorizontal=\"16dp\"         android:layout_marginTop=\"64dp\"         android:hint=\"@string\/email\"         app:endIconDrawable=\"@drawable\/clear\"         app:endIconMode=\"clear_text\"         app:layout_constraintEnd_toEndOf=\"parent\"         app:layout_constraintStart_toStartOf=\"parent\"         app:layout_constraintTop_toTopOf=\"parent\">          &lt;com.google.android.material.textfield.TextInputEditText             android:id=\"@+id\/mail_edittext\"             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:inputType=\"text\" \/>      &lt;\/ru.anb.passwordapp.features.ui.input.MailInput>      &lt;Button         android:id=\"@+id\/sign_in\"         android:layout_width=\"wrap_content\"         android:layout_height=\"wrap_content\"         android:layout_marginTop=\"32dp\"         android:text=\"@string\/sign_in\"         app:layout_constraintEnd_toStartOf=\"@+id\/navigate_to_sign_up\"         app:layout_constraintStart_toStartOf=\"parent\"         app:layout_constraintTop_toBottomOf=\"@+id\/auth_password\" \/>      &lt;Button         android:id=\"@+id\/navigate_to_sign_up\"         android:layout_width=\"wrap_content\"         android:layout_height=\"wrap_content\"         android:layout_marginTop=\"32dp\"         android:text=\"@string\/sign_up\"         app:layout_constraintEnd_toEndOf=\"parent\"         app:layout_constraintStart_toEndOf=\"@+id\/sign_in\"         app:layout_constraintTop_toBottomOf=\"@+id\/auth_password\" \/>      &lt;FrameLayout         android:id=\"@+id\/progress_bar\"         android:layout_width=\"match_parent\"         android:layout_height=\"match_parent\"         android:background=\"@color\/transparent\"         android:visibility=\"gone\"         app:layout_constraintBottom_toBottomOf=\"parent\"         app:layout_constraintEnd_toEndOf=\"parent\"         app:layout_constraintStart_toStartOf=\"parent\"         app:layout_constraintTop_toTopOf=\"parent\">          &lt;ProgressBar             android:layout_width=\"wrap_content\"             android:layout_height=\"wrap_content\"             android:layout_gravity=\"center\" \/>     &lt;\/FrameLayout>  &lt;\/androidx.constraintlayout.widget.ConstraintLayout><\/code><\/pre>\n<p>\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430 PasswordLayout.<\/p>\n<pre><code class=\"xml\">&lt;merge 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=\"wrap_content\"     tools:parentTag=\"android.widget.LinearLayout\">      &lt;ru.anb.passwordapp.features.ui.input.PasswordInput         android:id=\"@+id\/password_layout\"         style=\"@style\/Widget.Material3.TextInputLayout.OutlinedBox\"         android:layout_width=\"match_parent\"         android:layout_height=\"wrap_content\"         android:layout_marginHorizontal=\"16dp\"         android:layout_marginVertical=\"16dp\"         android:hint=\"@string\/password\"         app:endIconDrawable=\"@drawable\/eye\"         app:endIconMode=\"password_toggle\">          &lt;com.google.android.material.textfield.TextInputEditText             android:id=\"@+id\/password_edit_text\"             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:inputType=\"textPassword\" \/>      &lt;\/ru.anb.passwordapp.features.ui.input.PasswordInput>      &lt;ru.anb.passwordapp.features.ui.input.PasswordInput         android:id=\"@+id\/password_repeat_layout\"         style=\"@style\/Widget.Material3.TextInputLayout.OutlinedBox\"         android:layout_width=\"match_parent\"         android:layout_height=\"wrap_content\"         android:layout_marginHorizontal=\"16dp\"         android:hint=\"@string\/check_password\"         app:endIconDrawable=\"@drawable\/eye\"         app:endIconMode=\"password_toggle\">          &lt;com.google.android.material.textfield.TextInputEditText             android:id=\"@+id\/password_repeat_edit_text\"             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:inputType=\"textPassword\" \/>      &lt;\/ru.anb.passwordapp.features.ui.input.PasswordInput>      &lt;TextView         android:id=\"@+id\/error_text\"         android:layout_width=\"match_parent\"         android:layout_height=\"wrap_content\"         android:gravity=\"center\"         android:textColor=\"@color\/red\" \/>  &lt;\/merge><\/code><\/pre>\n<p>\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430 RegistrationFragment.<\/p>\n<pre><code class=\"xml\">&lt;FrameLayout 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\">       &lt;LinearLayout         android:layout_width=\"match_parent\"         android:layout_height=\"wrap_content\"         android:gravity=\"center_horizontal\"         android:orientation=\"vertical\"         tools:context=\".features.auth.ui.RegisterFragment\">          &lt;ru.anb.passwordapp.features.ui.input.MailInput             android:id=\"@+id\/sign_up_email\"             style=\"@style\/Widget.Material3.TextInputLayout.OutlinedBox\"             android:layout_width=\"match_parent\"             android:layout_height=\"wrap_content\"             android:layout_marginHorizontal=\"16dp\"             android:layout_marginTop=\"64dp\"             android:hint=\"@string\/email\"             android:inputType=\"text\"             app:endIconDrawable=\"@drawable\/clear\"             app:endIconMode=\"clear_text\">              &lt;com.google.android.material.textfield.TextInputEditText                 android:id=\"@+id\/register_login\"                 android:layout_width=\"match_parent\"                 android:layout_height=\"wrap_content\"                 android:inputType=\"text\" \/>          &lt;\/ru.anb.passwordapp.features.ui.input.MailInput>          &lt;ru.anb.passwordapp.features.ui.input.PasswordLayout             android:id=\"@+id\/sign_up_password_layout\"             android:layout_width=\"match_parent\"             android:layout_height=\"match_parent\" \/>           &lt;Button             android:id=\"@+id\/start_sign_up\"             android:layout_width=\"wrap_content\"             android:layout_height=\"wrap_content\"             android:layout_marginTop=\"16dp\"             android:text=\"@string\/sign_up\" \/>      &lt;\/LinearLayout>      &lt;FrameLayout         android:id=\"@+id\/progress_bar_registration\"         android:layout_width=\"match_parent\"         android:layout_height=\"match_parent\"         android:background=\"@color\/transparent\"         android:visibility=\"gone\">          &lt;ProgressBar             android:layout_width=\"wrap_content\"             android:layout_height=\"wrap_content\"             android:layout_gravity=\"center\" \/>     &lt;\/FrameLayout> &lt;\/FrameLayout><\/code><\/pre>\n<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e TextInputLayout \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 Custom View. \u0422\u0430\u043a \u0436\u0435, \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435, \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0442\u0430\u043a\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u043a\u0430\u043a app:endIconMode=&#187;password_toggle&#187; \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0447\u0442\u043e \u0432\u0432\u043e\u0434\u0438\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432 \u043f\u043e\u043b\u044f\u0445 password, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0441\u0442\u0440\u043e\u043a\u0438  app:endIconMode=&#187;clear_text&#187; \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0442\u0435\u0440\u0435\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u0431\u044b\u043b\u043e \u0440\u0430\u043d\u0435\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u043f\u043e\u043b\u0435 email.<\/p>\n<p>\u041d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0431\u0443\u0434\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0441\u00a0\u043f\u043e\u043c\u043e\u0449\u044c\u044e Navigation Components. \u0422\u0430\u043a\u00a0\u0436\u0435, \u0432\u00a0\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u0434\u043b\u044f\u00a0\u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d Hilt.<\/p>\n<p>\u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f:<\/p>\n<ol>\n<li>\n<p>\u043a\u043b\u0430\u0441\u0441 App (\u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u043c\u0430\u043d\u0438\u0444\u0435\u0441\u0442\u0435)<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">@HiltAndroidApp class App : Application()<\/code><\/pre>\n<ol start=\"2\">\n<li>\n<p>\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 AppComponent<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">@Component interface AppComponent { }<\/code><\/pre>\n<ol start=\"3\">\n<li>\n<p>\u043a\u043b\u0430\u0441\u0441 AuthModule &#8212; \u0432 \u044d\u0442\u043e\u043c \u043c\u043e\u0434\u0443\u043b\u0435 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f firebase.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">@InstallIn(SingletonComponent::class) @Module class AuthModule {      @Provides     @Singleton     fun provideFirebaseAuth(): FirebaseAuth {         return Firebase.auth     } }<\/code><\/pre>\n<ol start=\"4\">\n<li>\n<p>\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 Module, \u0441 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u043c  bindAuthRepository(), \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 AuthRepositoryImpl \u0441 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c AuthRepository (\u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u043d\u0438\u0436\u0435).<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">@InstallIn(SingletonComponent::class) @Module abstract class Module {      @Binds     abstract fun bindAuthRepository(authRepositoryImpl: AuthRepositoryImpl): AuthRepository }<\/code><\/pre>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u043e\u0433\u043e firebase, \u043e\u043f\u0443\u0449\u0443 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0435\u0433\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u0432 \u0441\u0430\u043c\u043e\u043c firebase \u0432\u0441\u0435 \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e, \u0434\u043e\u0431\u0430\u0432\u043b\u044e \u043b\u0438\u0448\u044c \u0442\u043e \u0447\u0442\u043e \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c implementation &#171;com.google.firebase:firebase-auth-ktx&#187; \u0430 \u0442\u0430\u043a\u0436\u0435 \u0432 \u0441\u0430\u043c\u043e\u043c firebase \u043d\u0443\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c, \u0447\u0442\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e email \u0438 password.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/34c\/c81\/ae7\/34cc81ae7538d635d3fa408eb4756a4a.PNG\" alt=\"\u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u0447\u0442\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e email \u0438 password.\" title=\"\u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u0447\u0442\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e email \u0438 password.\" width=\"1580\" height=\"361\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043c\u0435\u0447\u0430\u0435\u043c \u0447\u0442\u043e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e email \u0438 password.<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u0430\u043b\u0435\u0435, \u043d\u0443\u0436\u0435\u043d abstract class User.<\/p>\n<pre><code class=\"kotlin\">abstract class User {      abstract val email: String     abstract val id: String      class Base(override val email: String, override val id: String) : User()      object Empty : User() {         override val email = \"Empty\"         override val id = \"Empty_id\"     } }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b User \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 email \u0438 id, \u0432\u043a\u043b\u044e\u0447\u0430\u044f &#171;\u0431\u0430\u0437\u043e\u0432\u044b\u0435&#187; \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 Base \u0438 &#171;\u043f\u0443\u0441\u0442\u043e\u0433\u043e&#187; \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f Empty.    <\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 AuthRepositiry, \u0432 \u043d\u0435\u043c \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"kotlin\">interface AuthRepository {      suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult      suspend fun signUpWithEmailAndPassword(email: String, password: String): AuthResult }<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u0435\u043d \u043a\u043b\u0430\u0441\u0441 AuthResult, \u0432 \u043d\u0435\u043c \u0431\u0443\u0434\u0443\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u043e\u0442 firebase.<\/p>\n<pre><code class=\"kotlin\">sealed class AuthResult {      class Success(val user: User) : AuthResult()      class Error(val e: Exception) : AuthResult()      object Loading : AuthResult() }<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 AuthRepositiryImpl, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 AuthRepositiry, \u0433\u0434\u0435 \u0431\u0443\u0434\u0443\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0435\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u044b.<\/p>\n<pre><code class=\"kotlin\">class AuthRepositoryImpl @Inject constructor(private val auth: FirebaseAuth) : AuthRepository {      override suspend fun signInWithEmailAndPassword(email: String, password: String): AuthResult {         return try {             val user = auth.signInWithEmailAndPassword(email, password).await().user!!             AuthResult.Success(User.Base(user.email ?: \" \", user.uid))         } catch (e: Exception) {             AuthResult.Error(e)         }     }      override suspend fun signUpWithEmailAndPassword(email: String, password: String): AuthResult {         return try {             val user = auth.createUserWithEmailAndPassword(email, password).await().user!!             AuthResult.Success(User.Base(user.email ?: \" \", user.uid))         } catch (e: Exception) {             AuthResult.Error(e)         }     } }<\/code><\/pre>\n<p>\u0412 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 AuthRepositoryImpl \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 @Inject \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 auth \u0442\u0438\u043f\u0430 FirebaseAuth. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 FirebaseAuth \u0438\u0437 Hilt \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430.<\/p>\n<ol>\n<li>\n<p>signInWithEmailAndPassword &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438 \u043f\u0430\u0440\u043e\u043b\u044f. \u041e\u043d\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 signInWithEmailAndPassword \u0438\u0437 FirebaseAuth \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u0415\u0441\u043b\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u043b\u0430\u0441\u044c \u0443\u0441\u043f\u0435\u0448\u043d\u043e, \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 User.Base \u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u043e\u0439 \u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f AuthResult.Success. \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f AuthResult.Error <\/p>\n<\/li>\n<li>\n<p>signUpWithEmailAndPassword \u2013 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e.<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u0434 \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437, \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 BaseFragment \u0438 \u043a\u043b\u0430\u0441\u0441 BaseViewModel , \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u043e\u0431\u0449\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<pre><code class=\"kotlin\">abstract class BaseFragment&lt;B : ViewBinding> : Fragment() {     protected abstract val bindingInflater: (LayoutInflater, ViewGroup?) -> B     private var _binding: B? = null     protected val binding get() = _binding!!      override fun onCreateView(         inflater: LayoutInflater, container: ViewGroup?,         savedInstanceState: Bundle?     ): View {         _binding = bindingInflater.invoke(inflater, container)         return binding.root     }      override fun onDestroyView() {         super.onDestroyView()         _binding = null     } }<\/code><\/pre>\n<p>BaseFragment &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0442\u0438\u043f\u043e\u043c B, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 Fragment.<\/p>\n<ol>\n<li>\n<p>bindingInflater &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043e \u0432 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441\u0430\u0445 BaseFragment. \u041e\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0435\u0435 LayoutInflater \u0438 ViewGroup?, \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0435\u0435 B (\u0442\u0438\u043f, \u0443\u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 ViewBinding). <\/p>\n<\/li>\n<li>\n<p>_binding &#8212; \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e (binding) \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430. \u041e\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c null \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p>binding &#8212; \u0437\u0430\u0449\u0438\u0449\u0435\u043d\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e (binding). <\/p>\n<\/li>\n<li>\n<p>onCreateView &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 Fragment, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430. <\/p>\n<\/li>\n<li>\n<p>onDestroyView &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0438\u0437 \u043a\u043b\u0430\u0441\u0441\u0430 Fragment, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0443\u043d\u0438\u0447\u0442\u043e\u0436\u0435\u043d\u0438\u0438 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430. \u0412 \u044d\u0442\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0430 \u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e (_binding) \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 null \u0434\u043b\u044f \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">abstract class BaseViewModel : ViewModel() {      abstract val sendRequest: suspend (String, String) -> AuthResult      private val _authState = MutableLiveData&lt;AuthResult>()      val authState: LiveData&lt;AuthResult> get() = _authState      fun sendCredentials(email: String, password: String) {         viewModelScope.launch(Dispatchers.IO) {             _authState.postValue(AuthResult.Loading)             val result = sendRequest.invoke(email, password)             _authState.postValue(result)         }     } }<\/code><\/pre>\n<p>BaseViewModel &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439\u0441\u044f \u043e\u0442 ViewModel. \u041e\u043d \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439) \u0432 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 MVVM.<\/p>\n<ol>\n<li>\n<p>sendRequest &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u0432 \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441\u0430\u0445 BaseViewModel. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0434\u0432\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 (String) &#8212; \u0430\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438 \u043f\u0430\u0440\u043e\u043b\u044c, \u0438 \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0442\u0438\u043f\u0430 AuthResult. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u043a\u043b\u0430\u0441\u0441\u0430\u043c BaseViewModel \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u00a0_authState &#8212; \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0442\u0438\u043f\u0430 MutableLiveData&lt;AuthResult>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. \u041e\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c MutableLiveData, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u043c \u0442\u0438\u043f AuthResult.<\/p>\n<\/li>\n<li>\n<p>\u00a0authState &#8212; \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0442\u0438\u043f\u0430 LiveData&lt;AuthResult>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 authState.value. \u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>sendCredentials &#8212; \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 (firebase). \u041e\u043d\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 viewModelScope \u0441 \u0438\u0441\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u0435\u043c Dispatchers.IO, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0444\u043e\u043d\u043e\u0432\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435. \u0412\u043d\u0443\u0442\u0440\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 AuthResult.Loading, \u0437\u0430\u0442\u0435\u043c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f sendRequest \u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438 \u043f\u0430\u0440\u043e\u043b\u044f, \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432 _authState.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u044b \u0438 \u0432\u044c\u044e \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 View.<\/p>\n<pre><code class=\"kotlin\">@HiltViewModel class AuthorizationViewModel @Inject constructor(private val authRepository: AuthRepository) :     BaseViewModel() {      override val sendRequest: suspend (String, String) -> AuthResult =         { email, password -> authRepository.signInWithEmailAndPassword(email, password) }  }<\/code><\/pre>\n<p>AuthorizationViewModel &#8212; \u043a\u043b\u0430\u0441\u0441, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 ViewModel. \u041e\u043d \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 BaseViewModel.<\/p>\n<ol>\n<li>\n<p>@HiltViewModel &#8212; \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f ViewModel, \u0438 \u0435\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Hilt.<\/p>\n<\/li>\n<li>\n<p> authRepository &#8212; \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u0442\u0438\u043f\u0430 AuthRepository, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043d\u0435\u0434\u0440\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 AuthorizationViewModel \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 @Inject, \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u043d\u0435\u0434\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 Hilt.<\/p>\n<\/li>\n<li>\n<p> sendRequest &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0438\u0437 BaseViewModel, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u044e (String, String) -> AuthResult. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043e\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u0430\u043a \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 email \u0438 password \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 authRepository.signInWithEmailAndPassword \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438. authRepository.signInWithEmailAndPassword \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 AuthResult.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">@HiltViewModel class RegistrationViewModel @Inject constructor(private val authRepository: AuthRepository) :     BaseViewModel() {      override val sendRequest: suspend (String, String) -> AuthResult =         { email, password -> authRepository.signUpWithEmailAndPassword(email, password) }  }<\/code><\/pre>\n<p>RegistrationViewModel\u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0441 AuthorizationViewModel, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0432 sendRequest  email \u0438 password \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442\u0441\u044f \u0432 signUpWithEmailAndPassword.<\/p>\n<pre><code class=\"kotlin\">@AndroidEntryPoint class AuthorizationFragment : BaseFragment&lt;FragmentAuthorizationBinding>() {     override val bindingInflater: (LayoutInflater, ViewGroup?) -> FragmentAuthorizationBinding =         { inflater, container ->             FragmentAuthorizationBinding.inflate(inflater, container, false)         }      private val viewModel: AuthorizationViewModel by viewModels()      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {         super.onViewCreated(view, savedInstanceState)          val inputList = listOf(             binding.authMail,             binding.authPassword         )          viewModel.authState.observe(viewLifecycleOwner) {             when (it) {                 AuthResult.Loading -> binding.progressBar.visibility = View.VISIBLE                 is AuthResult.Error -> {                     binding.progressBar.visibility = View.GONE                     Toast.makeText(requireContext(), it.e.message.toString(), Toast.LENGTH_LONG)                         .show()                 }                  is AuthResult.Success -> {                     findNavController().navigate(R.id.action_authorizationFragment_to_homeFragment)                 }             }         }          binding.signIn.setOnClickListener {             val allValidation = inputList.map { it.isValid() }              if (allValidation.all { it }) {                 viewModel.sendCredentials(                     email = binding.authMail.text(),                     password = binding.authPassword.text()                 )             }         }         binding.navigateToSignUp.setOnClickListener {             findNavController().navigate(R.id.action_authorizationFragment_to_registrationFragment)         }      } }<\/code><\/pre>\n<ul>\n<li>\n<p>AuthorizationFragment &#8212; \u043a\u043b\u0430\u0441\u0441 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430, \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 BaseFragment&lt;FragmentAuthorizationBinding>.<\/p>\n<\/li>\n<li>\n<p>@AndroidEntryPoint &#8212; \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f Android-\u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0432\u043d\u0435\u0434\u0440\u0435\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e Hilt.<\/p>\n<\/li>\n<li>\n<p>bindingInflater &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e \u0438\u0437 BaseFragment, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044e (binding). \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043e\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 FragmentAuthorizationBinding.inflate \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 FragmentAuthorizationBinding \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>viewModel &#8212; \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 AuthorizationViewModel.<\/p>\n<\/li>\n<li>\n<p>val inputList = listOf(binding.authMail, binding.authPassword) &#8212; \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043f\u0438\u0441\u043e\u043a inputList, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0430\u0434\u0440\u0435\u0441\u0430 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0438 \u043f\u0430\u0440\u043e\u043b\u044f.<\/p>\n<\/li>\n<li>\n<p>viewModel.authState.observe(viewLifecycleOwner) { authResult -> &#8230; } &#8212; \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0442\u0435\u043b\u044c (observe) \u043d\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e authState \u0438\u0437 viewModel. \u041a\u043e\u0433\u0434\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f, \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f. \u0412\u043d\u0443\u0442\u0440\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430 \u043b\u043e\u0433\u0438\u043a\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f authResult:<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 authResult \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f AuthResult.Loading, \u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441-\u0431\u0430\u0440 (binding.progressBar) \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432\u0438\u0434\u0438\u043c\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 authResult \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f AuthResult.Error, \u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0435\u0441\u0441-\u0431\u0430\u0440 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f, \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442\u0441\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 (Toast) \u0441 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435 \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 authResult.e.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 authResult \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f AuthResult.Success, \u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e findNavController().navigate(R.id.action_authorizationFragment_to_homeFragment).<\/p>\n<\/li>\n<li>\n<p>binding.signIn.setOnClickListener { &#8230; } &#8212; \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 signIn. \u041a\u043e\u0433\u0434\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442\u0441\u044f, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0412\u043d\u0443\u0442\u0440\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 (inputList), \u0438 \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u043f\u0440\u043e\u0448\u043b\u0438 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e (allValidation.all { it }), \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 viewModel.sendCredentials, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0443\u0447\u0435\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 (email \u0438 password) \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 (firebase) \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>binding.navigateToSignUp.setOnClickListener { &#8230; } &#8212; \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043a\u0438 navigateToSignUp. \u041a\u043e\u0433\u0434\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0430\u0436\u0438\u043c\u0430\u0435\u0442\u0441\u044f, \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u0432\u043d\u0443\u0442\u0440\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0412\u043d\u0443\u0442\u0440\u0438 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043a \u0434\u0440\u0443\u0433\u043e\u043c\u0443 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0443 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e findNavController().navigate(R.id.action_authorizationFragment_to_registrationFragment).<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"kotlin\">@AndroidEntryPoint class RegistrationFragment : BaseFragment&lt;FragmentRegistrationBinding>() {     override val bindingInflater: (LayoutInflater, ViewGroup?) -> FragmentRegistrationBinding =         { inflater, container ->             FragmentRegistrationBinding.inflate(inflater, container, false)          }     private val viewModel: RegistrationViewModel by viewModels()      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {         super.onViewCreated(view, savedInstanceState)          val inputList = listOf(             binding.signUpEmail,             binding.signUpPasswordLayout         )          viewModel.authState.observe(viewLifecycleOwner) {             when (it) {                 AuthResult.Loading -> binding.progressBarRegistration.visibility = View.VISIBLE                 is AuthResult.Error -> {                     binding.progressBarRegistration.visibility = View.GONE                     Toast.makeText(requireContext(), it.e.message.toString(), Toast.LENGTH_LONG)                         .show()                 }                  is AuthResult.Success -> {                     findNavController().navigate(R.id.action_registrationFragment_to_homeFragment)                 }             }         }          binding.startSignUp.setOnClickListener {             val allValidation = inputList.map { it.isValid() }             if (allValidation.all { it }) {                 viewModel.sendCredentials(                     email = binding.signUpEmail.text(),                     password = binding.signUpPasswordLayout.text()                 )             }         }     } }<\/code><\/pre>\n<p>RegistrationFragment \u0443\u0441\u0442\u0440\u043e\u0435\u043d \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0434\u0435\u0442\u0430\u043b\u0435\u0439 \u0432 onViewCreated<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c. <\/p>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/0cb\/af8\/0ad\/0cbaf80ad527ac93f9ed653c55056352.jpg\" alt=\"\u0412\u0432\u043e\u0434 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445\" title=\"\u0412\u0432\u043e\u0434 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"1080\" height=\"2400\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/0cb\/af8\/0ad\/0cbaf80ad527ac93f9ed653c55056352.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0412\u0432\u043e\u0434 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/figcaption><\/div>\n<\/figure>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/c59\/903\/760\/c59903760972a554e39136a0f6585bb3.jpg\" alt=\"\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u0438 \u0432\u0432\u043e\u0434\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\" title=\"\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u0438 \u0432\u0432\u043e\u0434\u0435 \u0434\u0430\u043d\u043d\u044b\u0445\" width=\"1080\" height=\"2400\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c59\/903\/760\/c59903760972a554e39136a0f6585bb3.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u0438 \u0432\u0432\u043e\u0434\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/figcaption><\/div>\n<\/figure>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/d49\/b4e\/e93\/d49b4ee93834a1e2169c22246f7d555f.jpg\" alt=\"\u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u044b, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\" title=\"\u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u044b, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\" width=\"1080\" height=\"2400\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d49\/b4e\/e93\/d49b4ee93834a1e2169c22246f7d555f.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u044b, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/figcaption><\/div>\n<\/figure>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/1c6\/5bc\/b91\/1c65bcb91cc6a35b77dc9ae89b43b308.jpg\" alt=\"\u0415\u0441\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u043f\u0438\u0441\u044c \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\" title=\"\u0415\u0441\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u043f\u0438\u0441\u044c \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\" width=\"1080\" height=\"2400\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1c6\/5bc\/b91\/1c65bcb91cc6a35b77dc9ae89b43b308.jpg\" data-blurred=\"true\"\/><\/p>\n<div><figcaption>\u0415\u0441\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u043f\u043e\u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0434\u043f\u0438\u0441\u044c \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442<\/figcaption><\/div>\n<\/figure>\n<h2>\u0418\u0442\u043e\u0433  <\/h2>\n<p>\u0414\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u044b\u043c, \u0435\u0433\u043e \u043b\u0435\u0433\u043a\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c firebase \u043d\u0430 \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0435\u0440, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u043f\u043e\u043b\u044f \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0438\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0438\u0438 \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430. <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0441\u0432\u043e\u0435\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0435, \u0442\u043e \u0432\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0432\u043e\u0439 google-services.json. \u0411\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f \u0441 \u043a\u043e\u0434\u043e\u043c \u043c\u043e\u0436\u043d\u043e <a href=\"https:\/\/github.com\/Andrey9595\/PasswordApp\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442<\/a>.<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/768166\/\"> https:\/\/habr.com\/ru\/articles\/768166\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438 \u0425\u0430\u0431\u0440!<\/p>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0430\u0441 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0438 \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a. \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c \u0441\u0442\u043e\u0438\u0442 \u0431\u043e\u043b\u0435\u0435 \u0432\u0430\u0436\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c View \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e\u0431\u044b \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0432\u0435\u0434\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0431\u044b\u043b\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0432\u0435\u0434\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u043e \u0441\u0432\u043e\u0435\u0433\u043e email \u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0438\u043b\u0438 \u043d\u0430\u043f\u0438\u0448\u0435\u0442 \u043f\u0430\u0440\u043e\u043b\u044c \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0446\u0438\u0444\u0440\u044b? \u0412 \u043d\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445 \u044d\u0442\u043e \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e! \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043f\u0440\u043e\u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Custom View \u0438 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0432 firebase.<\/p>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u0414\u0430\u043d\u043d\u043e\u0435 \u0434\u0435\u043c\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u043a\u0442\u0438\u0432\u0438\u0442\u0438 \u0438 \u0442\u0440\u0438 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u2013 \u044d\u043a\u0440\u0430\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u0442\u043e\u0440\u043e\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u2013 \u044d\u043a\u0440\u0430\u043d \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c, \u0435\u0441\u043b\u0438 \u043e\u043d \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043f\u0440\u043e\u0448\u0435\u043b \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u043e\u0432. \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f, \u043a\u0430\u043a \u044f \u043f\u0438\u0441\u0430\u043b \u0440\u0430\u043d\u0435\u0435, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 firebase.<\/p>\n<h2>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f   <\/h2>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 Custom View \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u043b\u0435\u0439 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u0442\u0435\u043a\u0441\u0442\u0430, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u043a\u043e\u0434 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437, \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0443, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0438 \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043b\u0430\u0441\u0441\u044b, \u0442\u0430\u043a\u0438\u043c \u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0431\u0443\u0434\u0435\u0442 CustomInputLayout.<\/p>\n<pre><code class=\"kotlin\">abstract class CustomInputLayout @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : TextInputLayout(context, attrs, defStyleAttr), Validation {      protected abstract val errorMessageId: Int     private val textWatcher = RegistrationTextWatcher { error = \"\" }      open fun text() = editText?.text.toString()      override fun onAttachedToWindow() {         super.onAttachedToWindow()         editText?.addTextChangedListener(textWatcher)     }      override fun isValid(): Boolean {         val isValid = innerIsValid()         error = if (isValid) \"\" else context.getString(errorMessageId)         return isValid     }      protected abstract fun innerIsValid(): Boolean }  interface Validation {     fun isValid(): Boolean }<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 CustomInputLayout, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0430 TextInputLayout \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Android Material Design. CustomInputLayout \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Validation.<\/p>\n<p>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b context, attrs \u0438 defStyleAttr, \u0433\u0434\u0435 context \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, attrs \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435, \u0430 defStyleAttr &#8212; \u0441\u0442\u0438\u043b\u044c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d \u043a \u043c\u0430\u043a\u0435\u0442\u0443.<\/p>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u044b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0447\u043b\u0435\u043d\u044b:<\/p>\n<ol>\n<li>\n<p>errorMessageId &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u043e\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0435\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>textWatcher &#8212; \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 RegistrationTextWatcher \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043f\u043e\u043b\u0435 \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>text() &#8212; \u00a0\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0443 \u0442\u0435\u043a\u0441\u0442\u0430 \u0438\u0437 \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>onAttachedToWindow() &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 textWatcher \u043a \u043f\u043e\u043b\u044e \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>isValid() &#8212; \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 Validation, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 true, \u0435\u0441\u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c, \u0438 false &#8212; \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<\/li>\n<li>\n<p>innerIsValid() &#8212; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0438\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u043a\u043b\u0430\u0441\u0441\u0430\u0445-\u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u0430\u0445.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043a\u043b\u0430\u0441\u0441 RegistrationTextWatcher, \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0432 CustomInputLayout.<\/p>\n<pre><code class=\"kotlin\">class RegistrationTextWatcher(private val onTextChanged: () -> Unit) : TextWatcher {      override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {     }      override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {         onTextChanged.invoke()     }      override fun afterTextChanged(s: Editable?) {     } }<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 RegistrationTextWatcher \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044e onTextChanged, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430. \u042d\u0442\u043e \u0432\u044b\u0441\u043e\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 (Unit).<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043a\u043b\u0430\u0441\u0441 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0442\u0440\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 TextWatcher:<\/p>\n<ol>\n<li>\n<p>beforeTextChanged &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435\u043c \u0442\u0435\u043a\u0441\u0442\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043c\u0435\u0442\u043e\u0434 \u043d\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438 \u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043f\u0443\u0441\u0442\u044b\u043c.<\/p>\n<\/li>\n<li>\n<p>onTextChanged &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f onTextChanged.invoke(), \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 onTextChanged, \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u043e\u0439 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u0435 \u043a\u043b\u0430\u0441\u0441\u0430. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>afterTextChanged &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430. <\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043a\u043b\u0430\u0441\u0441 RegistrationTextWatcher \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u0432 \u043f\u043e\u043b\u0435 \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e onTextChanged, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u044d\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u043a\u043b\u0430\u0441\u0441, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u043b\u0430\u0441\u0441\u044b \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u043e\u043b\u0435\u0439 Email \u0438 Password, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0442\u044c \u043a \u0438\u0445 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"kotlin\">class MailInput @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : CustomInputLayout(context, attrs, defStyleAttr) {     override val errorMessageId = R.string.login_error      override fun innerIsValid(): Boolean {         return Patterns.EMAIL_ADDRESS.matcher(text()).matches()     } }<\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u043a\u043b\u0430\u0441\u0441 MailInput, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0441\u043b\u0435\u0434\u0443\u0435\u0442\u0441\u044f \u043e\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u043d\u0435\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 CustomInputLayout. \u042d\u0442\u043e\u0442 \u043a\u043b\u0430\u0441\u0441 \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u043b\u0435 \u0434\u043b\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b.<\/p>\n<p>\u041a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 MailInput \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>context: Context &#8212; \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>attrs: AttributeSet &#8212; \u043d\u0430\u0431\u043e\u0440 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432 XML-\u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0435 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0432\u0432\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p>defStyleAttr: Int &#8212; \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u0441\u0442\u0438\u043b\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<p>@JvmOverloads &#8212; \u044d\u0442\u043e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0430\u044f \u0434\u043b\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0445 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0442\u043e\u0440\u043e\u0432 \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0438\u0437 Java-\u043a\u043e\u0434\u0430.<\/p>\n<p>\u041a\u043b\u0430\u0441\u0441 MailInput \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ol>\n<li>\n<p>innerIsValid() &#8212; \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0432 \u043f\u043e\u043b\u0435 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c. <\/p>\n<\/li>\n<li>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 Java Patterns.EMAIL_ADDRESS.matcher(text()).matches(), \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c\u0443 \u0444\u043e\u0440\u043c\u0430\u0442\u0443 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b. \u0415\u0441\u043b\u0438 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0444\u043e\u0440\u043c\u0430\u0442\u0443, \u0442\u043e \u043c\u0435\u0442\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 &#8212; false.<\/p>\n<\/li>\n<li>\n<p>errorMessageId &#8212; \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 R.string.login_error. \u042d\u0442\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0431 \u043e\u0448\u0438\u0431\u043a\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e, \u0435\u0441\u043b\u0438 \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0442\u0435\u043a\u0441\u0442 \u043d\u0435 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b\u043c \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"kotlin\">class PasswordInput @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : CustomInputLayout(context, attrs, defStyleAttr) {      override val errorMessageId: Int = R.string.password_error      override fun innerIsValid(): Boolean {         return text().matches(Regex(PASSWORD_PATTERN))     }      companion object {          private const val PASSWORD_PATTERN =             \"^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@\\$%^&amp;*-]).{8,}\\$\"     } }<\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u043c\u0430\u043b\u043e \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u0439 <\/p>\n<p>errorMessageId \u2013 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0442\u0440\u043e\u043a\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 R.string.password_error.<\/p>\n<p>\u0410 \u0442\u0430\u043a\u0436\u0435 PASSWORD_PATTERN, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u043d \u043d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u0430\u043a EMAIL_ADDRESS, \u0431\u044b\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d.<\/p>\n<p>\u0414\u0430\u043d\u043d\u043e\u0435 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435:<\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0431\u0443\u043a\u0432\u0443 [A-Z].<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0441\u0442\u0440\u043e\u0447\u043d\u0443\u044e \u0431\u0443\u043a\u0432\u0443 [a-z].<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u043d\u0443 \u0446\u0438\u0444\u0440\u0443 [0-9].<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u0442 \u0445\u043e\u0442\u044f \u0431\u044b \u043e\u0434\u0438\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0438\u043c\u0432\u043e\u043b [#?!@\\$%^&amp;*-].<\/p>\n<\/li>\n<li>\n<p>\u0418\u043c\u0435\u044e\u0442 \u0434\u043b\u0438\u043d\u0443 \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 8 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 .{8,}.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0435 \u0441 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0435\u0439, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0438 \u043e\u0442 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442\u0430 \u0441 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0435\u0439, \u043a\u0440\u043e\u043c\u0435 \u043f\u043e\u043b\u044f \u0441 email \u0431\u0443\u0434\u0443\u0442 \u0434\u0432\u0430 \u043f\u043e\u043b\u044f password \u0433\u0434\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 \u043f\u0430\u0440\u043e\u043b\u0435\u0439.<\/p>\n<pre><code class=\"kotlin\">class PasswordLayout @JvmOverloads constructor(     context: Context,     attrs: AttributeSet,     defStyleAttr: Int = 0 ) : LinearLayout(context, attrs, defStyleAttr), Validation {      private val binding = PasswordLayoutBinding.inflate(LayoutInflater.from(context), this)      init {         orientation = VERTICAL         listOf(binding.passwordEditText, binding.passwordRepeatEditText).forEach {             it.addTextChangedListener(RegistrationTextWatcher {                 binding.errorText.text = \"\"             })         }     }      private val errorMessageId: Int = R.string.password_error_same      override fun isValid(): Boolean {         with(binding) {             val isPasswordsEquals = passwordLayout.text() == passwordRepeatLayout.text()             errorText.text = if (isPasswordsEquals) \"\" else context.getString(errorMessageId)             val isPasswordsValid = listOf(passwordLayout, passwordRepeatLayout).map { it.isValid() }             return isPasswordsValid.all { it } &amp;&amp; isPasswordsEquals         }     }      fun text(): String {         return binding.passwordLayout.text()     } }<\/code><\/pre>\n<p>\u041a\u043b\u0430\u0441\u0441 PasswordLayout \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e binding, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043d\u0444\u043b\u0435\u0439\u0442\u0438\u0442 \u043c\u0430\u043a\u0435\u0442 PasswordLayoutBinding \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c LayoutInflater \u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a \u0442\u0435\u043a\u0443\u0449\u0435\u043c\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0443 LinearLayout.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u0432 \u0431\u043b\u043e\u043a\u0435 init \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c\u043d\u0430\u044f \u043e\u0440\u0438\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f \u043c\u0430\u043a\u0435\u0442\u0430, \u0438 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f (passwordEditText \u0438 passwordRepeatEditText) \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f TextChangedListener, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043a\u0430\u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 RegistrationTextWatcher. \u042d\u0442\u043e\u0442 \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u043f\u043e\u043b\u044f\u0445 \u0432\u0432\u043e\u0434\u0430 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 (errorText) \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442 \u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f errorMessageId \u0445\u0440\u0430\u043d\u0438\u0442 R.string.password_error_same, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0441\u0442\u0430 \u043e\u0448\u0438\u0431\u043a\u0438, \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 isValid() \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 Validation \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u0430\u043b\u0438\u0434\u043d\u043e\u0441\u0442\u0438 \u043f\u0430\u0440\u043e\u043b\u044f \u0438 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f. \u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043c\u0435\u0442\u043e\u0434 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f passwordLayout \u0438 passwordRepeatLayout \u0432 \u043c\u0430\u043a\u0435\u0442\u0435 \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u043e\u0448\u0438\u0431\u043a\u0438 errorText \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f. \u0417\u0430\u0442\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u044e \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0438\u0437 \u043f\u043e\u043b\u0435\u0439 \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 true, \u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u043f\u043e\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u043d\u044b \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u0438 false \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435.<\/p>\n<p>\u041c\u0435\u0442\u043e\u0434 text() \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0442\u0435\u043a\u0441\u0442 \u0438\u0437 \u043f\u043e\u043b\u044f \u0432\u0432\u043e\u0434\u0430 \u043f\u0430\u0440\u043e\u043b\u044f passwordLayout \u0432 \u043c\u0430\u043a\u0435\u0442\u0435, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0432\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u043f\u0430\u0440\u043e\u043b\u044c \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0447\u0430\u0441\u0442\u044f\u0445 \u043a\u043e\u0434\u0430.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0432\u0435\u0440\u0441\u0442\u0430\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u044d\u043a\u0440\u0430\u043d\u043e\u0432.<\/p>\n<p>\u0420\u0430\u0437\u043c\u0435\u0442\u043a\u0430<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-357773","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/357773","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=357773"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/357773\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=357773"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=357773"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=357773"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}