Ho fatto un legante come la mia risposta su How to set error on EditText using DataBinding Framwork MVVM. Ma questa volta ha usato TextInputLayout come esempio, come il precedente.
scopi di questa idea:
- Fare il xml più leggibili possibile e indipendente
- Fare la convalida convalida di attività-side e xml-side in modo indipendente
Naturalmente, è possibile rendi la tua convalida e impostala utilizzando il tag <variable>
in xml
In primo luogo, implementa la statica metodo di associazione e le relative regole di convalida della stringa per la preparazione.
Binding
@BindingAdapter({"app:validation", "app:errorMsg"})
public static void setErrorEnable(TextInputLayout textInputLayout, StringRule stringRule,
final String errorMsg) {
}
StringRule
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);
}
In secondo luogo, mettere la validazione di default e il messaggio di errore nel TextInputLayout e rendere più facile per conoscere la convalida, vincolante in 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>
In terzo luogo, quando si attiva il pulsante clic, è possibile utilizzare l'ID predefinito in TextInputLayout (ad es. imageUrlValidation) per fare la validazione finale sull'attività
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();
}
});
Il codice completo è il seguente:
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();
});
}
}
Usa può leggere all'indirizzo: http://developer.android.com/intl/vi/tools/data-binding/guide.html. Ottieni il binding dall'attività, come: MainActivityBinding binding = DataBindingUtil.setContentView (this, R.layout.main_activity); e imposta valore da binding.setError ("String you want") –
Non si tratta proprio di una domanda. So già come eseguire il binding di base. – Theyouthis