我可以将错误消息绑定到 TextInputLayout 吗?
Can i bind an error message to a TextInputLayout?
我想将错误消息直接绑定到 android.support.design.widget.TextInputLayout
。我找不到通过布局设置错误的方法。这甚至可能吗?
这就是我想象中的工作方式:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<import type="android.view.View" />
<variable
name="error"
type="String" />
</data>
<android.support.v7.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true"
app:errorText="@{error}">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/username"
android:inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
</android.support.v7.widget.LinearLayoutCompat>
</layout>
在写这个答案时(2016年5月),没有XML属性对应setError()
方法,所以你不能直接在你的XML中设置错误信息,这是知道 errorEnabled
在那里有点奇怪。但是,可以通过创建 Binding Adapter 来填补空白并提供缺失的实现,从而轻松解决此问题。像这样:
@BindingAdapter("app:errorText")
public static void setErrorMessage(TextInputLayout view, String errorMessage) {
view.setError(errorMessage);
}
参见 official binding docs,“属性设置器”部分,尤其是“自定义设置器”。
编辑
Possibly dumb question, but where should i put this? Do I need to extend TextInputLayout
and put this in there?
其实这根本不是一个愚蠢的问题,只是因为你无法通过阅读官方文档获得完整的答案。幸运的是它非常简单:您不需要扩展任何东西 - 只需将该方法 anywhere 放在您的项目中。您可以创建单独的 class(即 DataBindingAdapters
)或仅将此方法添加到项目中任何现有的 class - 这并不重要。只要你用@BindingAdapter
注解这个方法,并且保证是public
和static
什么class都无所谓住在.
我已经像我在 How to set error on EditText using DataBinding Framwork MVVM 上的回答一样绑定了。但是这次它使用 TextInputLayout 作为示例,就像上一个一样。
这个想法的目的:
- 使 xml 尽可能可读且独立
- 独立进行activity端验证和xml端验证
当然,您可以自己验证并使用 xml
中的 <variable>
标签进行设置
首先,实现静态绑定方法和相关String校验规则准备。
绑定
@BindingAdapter({"app:validation", "app:errorMsg"})
public static void setErrorEnable(TextInputLayout textInputLayout, StringRule stringRule,
final String errorMsg) {
}
字符串规则
public static class Rule {
public static StringRule NOT_EMPTY_RULE = s -> TextUtils.isEmpty(s.toString());
public static StringRule EMAIL_RULE = s -> s.toString().length() > 18;
}
public interface StringRule {
boolean validate(Editable s);
}
其次,将默认的验证和错误信息放在TextInputLayout中,让验证一目了然,绑定在xml
<android.support.design.widget.TextInputLayout
android:id="@+id/imageUrlValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_imageUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Image Url"
android:text="@={feedEntry.imageUrl}" />
</android.support.design.widget.TextInputLayout>
第三,当点击按钮触发时,可以使用TextInputLayout中预定义的id(例如imageUrlValidation)对activity[=19=进行最终验证]
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(view1 -> {
// TODO Do something
//to trigger auto error enable
FeedEntry inputFeedEntry = dialogFeedEntryBinding.getFeedEntry();
Boolean[] validations = new Boolean[]{
dialogFeedEntryBinding.imageUrlValidation.isErrorEnabled(),
dialogFeedEntryBinding.titleValidation.isErrorEnabled(),
dialogFeedEntryBinding.subTitleValidation.isErrorEnabled()
};
boolean isValid = true;
for (Boolean validation : validations) {
if (validation) {
isValid = false;
}
}
if (isValid) {
new AsyncTask<FeedEntry, Void, Void>() {
@Override
protected Void doInBackground(FeedEntry... feedEntries) {
viewModel.insert(feedEntries);
return null;
}
}.execute(inputFeedEntry);
dialogInterface.dismiss();
}
});
完整代码如下:
dialog_feedentry.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.example.common.components.TextInputEditTextBindingUtil.Rule" />
<variable
name="feedEntry"
type="com.example.feedentry.repository.bean.FeedEntry" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/imageUrlValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_imageUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Image Url"
android:text="@={feedEntry.imageUrl}" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/titleValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Title"
android:text="@={feedEntry.title}"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/subTitleValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Subtitle"
android:text="@={feedEntry.subTitle}"
/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</layout>
TextInputEditTextBindingUtil.java
package com.example.common.components;
import android.databinding.BindingAdapter;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
/**
* Created by Charles Ng on 7/9/2017.
*/
public class TextInputEditTextBindingUtil {
@BindingAdapter({"app:validation", "app:errorMsg"})
public static void setErrorEnable(TextInputLayout textInputLayout, StringRule stringRule,
final String errorMsg) {
textInputLayout.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
textInputLayout
.setErrorEnabled(stringRule.validate(textInputLayout.getEditText().getText()));
if (stringRule.validate(textInputLayout.getEditText().getText())) {
textInputLayout.setError(errorMsg);
} else {
textInputLayout.setError(null);
}
}
});
textInputLayout
.setErrorEnabled(stringRule.validate(textInputLayout.getEditText().getText()));
if (stringRule.validate(textInputLayout.getEditText().getText())) {
textInputLayout.setError(errorMsg);
} else {
textInputLayout.setError(null);
}
}
public static class Rule {
public static StringRule NOT_EMPTY_RULE = s -> TextUtils.isEmpty(s.toString());
public static StringRule EMAIL_RULE = s -> s.toString().length() > 18;
}
public interface StringRule {
boolean validate(Editable s);
}
}
FeedActivity.java
public class FeedActivity extends AppCompatActivity {
private FeedEntryListViewModel viewModel;
@SuppressLint("StaticFieldLeak")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed);
viewModel = ViewModelProviders.of(this)
.get(FeedEntryListViewModel.class);
viewModel.init(this);
ViewPager viewPager = findViewById(R.id.viewpager);
setupViewPager(viewPager);
// Set Tabs inside Toolbar
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(view -> {
//insert sample data by button click
final DialogFeedentryBinding dialogFeedEntryBinding = DataBindingUtil
.inflate(LayoutInflater.from(this), R.layout.dialog_feedentry, null, false);
FeedEntry feedEntry = new FeedEntry("", "");
feedEntry.setImageUrl("http://i.imgur.com/DvpvklR.png");
dialogFeedEntryBinding.setFeedEntry(feedEntry);
final Dialog dialog = new AlertDialog.Builder(FeedActivity.this)
.setTitle("Create a new Feed Entry")
.setView(dialogFeedEntryBinding.getRoot())
.setPositiveButton("Submit", null)
.setNegativeButton("Cancel", (dialogInterface, i) -> dialogInterface.dismiss())
.create();
dialog.setOnShowListener(dialogInterface -> {
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(view1 -> {
// TODO Do something
//to trigger auto error enable
FeedEntry inputFeedEntry = dialogFeedEntryBinding.getFeedEntry();
Boolean[] validations = new Boolean[]{
dialogFeedEntryBinding.imageUrlValidation.isErrorEnabled(),
dialogFeedEntryBinding.titleValidation.isErrorEnabled(),
dialogFeedEntryBinding.subTitleValidation.isErrorEnabled()
};
boolean isValid = true;
for (Boolean validation : validations) {
if (validation) {
isValid = false;
}
}
if (isValid) {
new AsyncTask<FeedEntry, Void, Void>() {
@Override
protected Void doInBackground(FeedEntry... feedEntries) {
viewModel.insert(feedEntries);
return null;
}
}.execute(inputFeedEntry);
dialogInterface.dismiss();
}
});
});
dialog.show();
});
}
}
像这样定义你的xml
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/emailTextInputLayout"
style="@style/myTextInputLayoutStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="80dp"
android:layout_marginEnd="16dp"
**app:errorEnabled="true"**
**app:errorText="@{viewModel.emailErrorMessage}"**
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email"
android:inputType="textEmailAddress"
**android:text="@={viewModel.emailText}" />**
</com.google.android.material.textfield.TextInputLayout>
然后把这个方法放在任何地方
@BindingAdapter("app:errorText")
fun setErrorText(view: TextInputLayout, errorMessage: String) {
if (errorMessage.isEmpty())
view.error = null
else
view.error = errorMessage;
}
假设您将在单击按钮后进行验证,因此您的按钮将像这样
<Button
android:id="@+id/signInButtonView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="68dp"
android:layout_marginEnd="16dp"
**android:onClick="@{() -> viewModel.logIn()}"**
android:text="@string/sign_in"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordTextInputLayout" />
然后在你的视图模型中
你将拥有这些
class SignInViewModel : ViewModel() {
private val _emailErrorMessage = MutableLiveData("")
val emailText = MutableLiveData("")
val emailErrorMessage: LiveData<String> = _emailErrorMessage
fun logIn() {
if (validateInput()) {
}
}
private fun validateInput(): Boolean {
if (emailText.value?.length!! < 5) {
_emailErrorMessage.value = "no way"
return false
}
_emailErrorMessage.value = ""
return true
}
.
.
并且不要忘记将其添加到您的 activity 或片段中
binding.lifecycleOwner = this
代码很长所以我在重要的行上加了双星号
我想将错误消息直接绑定到 android.support.design.widget.TextInputLayout
。我找不到通过布局设置错误的方法。这甚至可能吗?
这就是我想象中的工作方式:
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<import type="android.view.View" />
<variable
name="error"
type="String" />
</data>
<android.support.v7.widget.LinearLayoutCompat
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true"
app:errorText="@{error}">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/username"
android:inputType="textEmailAddress" />
</android.support.design.widget.TextInputLayout>
</android.support.v7.widget.LinearLayoutCompat>
</layout>
在写这个答案时(2016年5月),没有XML属性对应setError()
方法,所以你不能直接在你的XML中设置错误信息,这是知道 errorEnabled
在那里有点奇怪。但是,可以通过创建 Binding Adapter 来填补空白并提供缺失的实现,从而轻松解决此问题。像这样:
@BindingAdapter("app:errorText")
public static void setErrorMessage(TextInputLayout view, String errorMessage) {
view.setError(errorMessage);
}
参见 official binding docs,“属性设置器”部分,尤其是“自定义设置器”。
编辑
Possibly dumb question, but where should i put this? Do I need to extend
TextInputLayout
and put this in there?
其实这根本不是一个愚蠢的问题,只是因为你无法通过阅读官方文档获得完整的答案。幸运的是它非常简单:您不需要扩展任何东西 - 只需将该方法 anywhere 放在您的项目中。您可以创建单独的 class(即 DataBindingAdapters
)或仅将此方法添加到项目中任何现有的 class - 这并不重要。只要你用@BindingAdapter
注解这个方法,并且保证是public
和static
什么class都无所谓住在.
我已经像我在 How to set error on EditText using DataBinding Framwork MVVM 上的回答一样绑定了。但是这次它使用 TextInputLayout 作为示例,就像上一个一样。
这个想法的目的:
- 使 xml 尽可能可读且独立
- 独立进行activity端验证和xml端验证
当然,您可以自己验证并使用 xml
中的<variable>
标签进行设置
首先,实现静态绑定方法和相关String校验规则准备。
绑定
@BindingAdapter({"app:validation", "app:errorMsg"})
public static void setErrorEnable(TextInputLayout textInputLayout, StringRule stringRule,
final String errorMsg) {
}
字符串规则
public static class Rule {
public static StringRule NOT_EMPTY_RULE = s -> TextUtils.isEmpty(s.toString());
public static StringRule EMAIL_RULE = s -> s.toString().length() > 18;
}
public interface StringRule {
boolean validate(Editable s);
}
其次,将默认的验证和错误信息放在TextInputLayout中,让验证一目了然,绑定在xml
<android.support.design.widget.TextInputLayout
android:id="@+id/imageUrlValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_imageUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Image Url"
android:text="@={feedEntry.imageUrl}" />
</android.support.design.widget.TextInputLayout>
第三,当点击按钮触发时,可以使用TextInputLayout中预定义的id(例如imageUrlValidation)对activity[=19=进行最终验证]
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(view1 -> {
// TODO Do something
//to trigger auto error enable
FeedEntry inputFeedEntry = dialogFeedEntryBinding.getFeedEntry();
Boolean[] validations = new Boolean[]{
dialogFeedEntryBinding.imageUrlValidation.isErrorEnabled(),
dialogFeedEntryBinding.titleValidation.isErrorEnabled(),
dialogFeedEntryBinding.subTitleValidation.isErrorEnabled()
};
boolean isValid = true;
for (Boolean validation : validations) {
if (validation) {
isValid = false;
}
}
if (isValid) {
new AsyncTask<FeedEntry, Void, Void>() {
@Override
protected Void doInBackground(FeedEntry... feedEntries) {
viewModel.insert(feedEntries);
return null;
}
}.execute(inputFeedEntry);
dialogInterface.dismiss();
}
});
完整代码如下:
dialog_feedentry.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="com.example.common.components.TextInputEditTextBindingUtil.Rule" />
<variable
name="feedEntry"
type="com.example.feedentry.repository.bean.FeedEntry" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:orientation="vertical">
<android.support.design.widget.TextInputLayout
android:id="@+id/imageUrlValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_imageUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Image Url"
android:text="@={feedEntry.imageUrl}" />
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/titleValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Title"
android:text="@={feedEntry.title}"
/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/subTitleValidation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:validation="@{Rule.NOT_EMPTY_RULE}"
app:errorMsg='@{"Cannot be empty"}'
>
<android.support.design.widget.TextInputEditText
android:id="@+id/input_subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Subtitle"
android:text="@={feedEntry.subTitle}"
/>
</android.support.design.widget.TextInputLayout>
</LinearLayout>
</layout>
TextInputEditTextBindingUtil.java
package com.example.common.components;
import android.databinding.BindingAdapter;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
/**
* Created by Charles Ng on 7/9/2017.
*/
public class TextInputEditTextBindingUtil {
@BindingAdapter({"app:validation", "app:errorMsg"})
public static void setErrorEnable(TextInputLayout textInputLayout, StringRule stringRule,
final String errorMsg) {
textInputLayout.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
textInputLayout
.setErrorEnabled(stringRule.validate(textInputLayout.getEditText().getText()));
if (stringRule.validate(textInputLayout.getEditText().getText())) {
textInputLayout.setError(errorMsg);
} else {
textInputLayout.setError(null);
}
}
});
textInputLayout
.setErrorEnabled(stringRule.validate(textInputLayout.getEditText().getText()));
if (stringRule.validate(textInputLayout.getEditText().getText())) {
textInputLayout.setError(errorMsg);
} else {
textInputLayout.setError(null);
}
}
public static class Rule {
public static StringRule NOT_EMPTY_RULE = s -> TextUtils.isEmpty(s.toString());
public static StringRule EMAIL_RULE = s -> s.toString().length() > 18;
}
public interface StringRule {
boolean validate(Editable s);
}
}
FeedActivity.java
public class FeedActivity extends AppCompatActivity {
private FeedEntryListViewModel viewModel;
@SuppressLint("StaticFieldLeak")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed);
viewModel = ViewModelProviders.of(this)
.get(FeedEntryListViewModel.class);
viewModel.init(this);
ViewPager viewPager = findViewById(R.id.viewpager);
setupViewPager(viewPager);
// Set Tabs inside Toolbar
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(view -> {
//insert sample data by button click
final DialogFeedentryBinding dialogFeedEntryBinding = DataBindingUtil
.inflate(LayoutInflater.from(this), R.layout.dialog_feedentry, null, false);
FeedEntry feedEntry = new FeedEntry("", "");
feedEntry.setImageUrl("http://i.imgur.com/DvpvklR.png");
dialogFeedEntryBinding.setFeedEntry(feedEntry);
final Dialog dialog = new AlertDialog.Builder(FeedActivity.this)
.setTitle("Create a new Feed Entry")
.setView(dialogFeedEntryBinding.getRoot())
.setPositiveButton("Submit", null)
.setNegativeButton("Cancel", (dialogInterface, i) -> dialogInterface.dismiss())
.create();
dialog.setOnShowListener(dialogInterface -> {
Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
button.setOnClickListener(view1 -> {
// TODO Do something
//to trigger auto error enable
FeedEntry inputFeedEntry = dialogFeedEntryBinding.getFeedEntry();
Boolean[] validations = new Boolean[]{
dialogFeedEntryBinding.imageUrlValidation.isErrorEnabled(),
dialogFeedEntryBinding.titleValidation.isErrorEnabled(),
dialogFeedEntryBinding.subTitleValidation.isErrorEnabled()
};
boolean isValid = true;
for (Boolean validation : validations) {
if (validation) {
isValid = false;
}
}
if (isValid) {
new AsyncTask<FeedEntry, Void, Void>() {
@Override
protected Void doInBackground(FeedEntry... feedEntries) {
viewModel.insert(feedEntries);
return null;
}
}.execute(inputFeedEntry);
dialogInterface.dismiss();
}
});
});
dialog.show();
});
}
}
像这样定义你的xml
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/emailTextInputLayout"
style="@style/myTextInputLayoutStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="80dp"
android:layout_marginEnd="16dp"
**app:errorEnabled="true"**
**app:errorText="@{viewModel.emailErrorMessage}"**
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/include">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email"
android:inputType="textEmailAddress"
**android:text="@={viewModel.emailText}" />**
</com.google.android.material.textfield.TextInputLayout>
然后把这个方法放在任何地方
@BindingAdapter("app:errorText")
fun setErrorText(view: TextInputLayout, errorMessage: String) {
if (errorMessage.isEmpty())
view.error = null
else
view.error = errorMessage;
}
假设您将在单击按钮后进行验证,因此您的按钮将像这样
<Button
android:id="@+id/signInButtonView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="68dp"
android:layout_marginEnd="16dp"
**android:onClick="@{() -> viewModel.logIn()}"**
android:text="@string/sign_in"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordTextInputLayout" />
然后在你的视图模型中
你将拥有这些
class SignInViewModel : ViewModel() {
private val _emailErrorMessage = MutableLiveData("")
val emailText = MutableLiveData("")
val emailErrorMessage: LiveData<String> = _emailErrorMessage
fun logIn() {
if (validateInput()) {
}
}
private fun validateInput(): Boolean {
if (emailText.value?.length!! < 5) {
_emailErrorMessage.value = "no way"
return false
}
_emailErrorMessage.value = ""
return true
}
.
.
并且不要忘记将其添加到您的 activity 或片段中
binding.lifecycleOwner = this
代码很长所以我在重要的行上加了双星号