I have a form where the user enter the client info. When I try to validate the fields I have a problem, I used editText.setError(errorMessage)
and it's showing the error message, but it shown on the top of my EditText making it confusing to the user. Like the image below.
Any ideas of how I can fix this?
EditText on XML
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="br.com.intelecto.intesigmobile.activity.ClienteEditActivityFragment">
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_nome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/cliente_nome"
android:imeActionId="@+id/cli_name"
android:imeActionLabel="@string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textPersonName"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_telefone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/cliente_telefone"
android:imeActionId="@+id/cli_cpf"
android:imeActionLabel="@string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="phone"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/cliente_email"
android:imeActionId="@+id/cli_cpf"
android:imeActionLabel="@string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textEmailAddress"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_cpf"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/cliente_cpf"
android:imeActionId="@+id/cli_cpf"
android:imeActionLabel="@string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="number"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_endereco"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/cliente_endereco"
android:imeActionId="@+id/cli_address"
android:imeActionLabel="@string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="textPostalAddress"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_bairro"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/cliente_bairro"
android:imeActionId="@+id/cli_district"
android:imeActionLabel="@string/str_next"
android:imeOptions="actionUnspecified"
android:inputType="text"
android:maxLines="1"
android:singleLine="true"/>
</android.support.design.widget.TextInputLayout>
<Spinner
android:id="@+id/sp_estados"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"/>
<Spinner
android:id="@+id/sp_cidade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:prompt="@string/cliente_cidade"/>
This ClienteEditActivity holds two fragments with different forms so I listen for a action menu click at the fragment, when menu is clicked I use this to call may validation:
if (!isValidEmail(etEmail)) {
cancel = true;
focusView = etEmail;
}
//after other validations
if (cancel){
focusView.reqeustFocus();
} else {
//save datas
}
The isValidEmail
method is like this:
protected boolean isValidEmail(EditText editText) {
validate = new Validate(editText);
validate.addValidador(new ValidadorVazio(getContext()));
validate.addValidador(new ValidadorEmail(getContext()));
return validate.isValid();
}
My Validate
class looks like this:
public class Validate{
private EditText etFonte;
public Validate(EditText etFonte){
this.etFonte = etFonte;
}
public void addValidador(AbstractValidador validador){
lalidadores.add(validador);
}
public boolean isValid(){
for (AbstractValidador validator : lValidadores) {
try {
if (!validator.isValid(etFonte.getText().toString())) {
if(errorNotification != null) {
errorNotification.onInvalid(this);
} else {
setSourceViewError(validator.getMessage(), validator.getErrorDrawable());
}
return false;
} else {
if(errorNotification != null) errorNotification.onValid(this);
}
} catch (ValidadorException e) {
e.printStackTrace();
if(errorNotification != null) {
errorNotification.onInvalid(this);
} else {
setSourceViewError(e.getMessage(),validator.getErrorDrawable());
}
return false;
}
}
etFonte.setError(null);
return true;
}
private void setSourceViewError(String errorMessage, Drawable errorDrawable) {
if(errorDrawable != null) {
etFonte.setError(errorMessage, errorDrawable);
} else {
etFonte.setError(errorMessage);
}
}
}