Validando TextViews

Los componentes DatePicker y TimePicker los considero muy poco ágiles para mi aplicación de productividad, así que he decidido cambiarlos por un componente CalendarView y dos TextView para informar la hora y los minutos.

Al hacer esto, tendremos que incluir la validación de los elementos de texto que representan la hora y los minutos. Ambos valores únicamente podrán contener dígitos, la hora estará comprendida entre 0 y 23 y los minutos entre 0 y 59.
Para validar un TextView se debe incluir un TextWatcher utilizando el método addTextChangedListener al componente TextView. Este listener implementa los métodos beforeTextChanged, onTextChanged y afterTextChanged.
En nuestro caso utilizaremos el método afterTextChanged ya que queremos validar el texto una vez se haya introducido el nuevo valor.
Cuando la validación no sea correcta y se quiere mostrar un mensaje, normalmente se utiliza el método setError, pero como el componente a validar está dentro de un LayoutInflater, no será posible usarlo y mostraremos el mensaje con un Toast.

Primero tendremos un calendario en una ventana popup, con un main_layout.xml, exactamente igual.

El layoutinflater.xml tendrá algunas modificaciones, se eliminan los dos pickers y se añade un Calendarview y dos Textviews.

Actualizaremos los ficheros strings.xml, dimens.xml y styles.xml para que los layouts se vean correctamente:
strings.xml

<resources>

    <string name="app_name">ValidateTutorial</string>
    <string name="action_settings">Settings</string>

    <string name="calendar_limpiar">Limpiar</string>
    <string name="calendar_aceptar">Aceptar</string>

    <string name="currentDate">Fecha actual(M-D-AAAA h:m):</string>
    <string name="calendar">Calendario</string>

    <string name="validaHora">Las horas deben estar comprendidas entre 0 y 23</string>
    <string name="validaMinutos">Los minutos deben estar comprendidos entre 0 y 59</string>
</resources>

dimens.xml

<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>

styles.xml

<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>
</resources>

La pantalla inicial se verá de la siguiente forma:
Pantalla_3_01

Al pulsar el botón calendario se abrirá la nueva ventana popup:
Pantalla_3_02

El control de las ventanas y de la funcionalidad a los botones y las validaciones se realizará desde la clase MainActivity.

package com.validatetutorial.validatetutorial;

import android.app.Activity;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CalendarView;
import android.widget.EditText;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

public class MainActivity extends Activity {

    private TextView tvDateValue;
    private boolean hourOK = true;
    private boolean minuteOK = true;

    private CalendarView calendar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        tvDateValue = (TextView) findViewById(R.id.dateValueLI);

        /**
         * Control del evento Click del Button Calendario
         */
        final Button btnOpenPopup = (Button) findViewById(R.id.btnCalendarLI);
        btnOpenPopup.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View arg0) {

                LayoutInflater layoutInflater
                        = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);

                View popupView = layoutInflater.inflate(R.layout.layoutinflater, (ViewGroup) arg0.findViewById(R.id.popup_element));

                final PopupWindow popupWindow = new PopupWindow(
                        popupView,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                        true);
                popupWindow.showAtLocation(popupView, Gravity.CENTER, 0, 0);

                calendar = (CalendarView) popupView.findViewById(R.id.calendarView);

                calendar.setShownWeekCount(4);

                final EditText edHour = (EditText) popupView.findViewById(R.id.hour);
                final EditText edMinute = (EditText) popupView.findViewById(R.id.minute);

                Calendar c = Calendar.getInstance();
                try {

                    if (tvDateValue.getText().length() &gt; 0) {
                        if (tvDateValue.getText().length() &gt; 10) {
                            SimpleDateFormat formatoDelTexto = new SimpleDateFormat("MM-dd-yyyy");
                            c.setTime(formatoDelTexto.parse(String.valueOf(tvDateValue.getText()).substring(0, 10)));
                            if (tvDateValue.getText().length() &gt; 14) {
                                String valueHour = String.valueOf(tvDateValue.getText()).substring(11, 13);
                                edHour.setText(valueHour);
                            }
                            if (tvDateValue.getText().length() == 16) {
                                String valueMinute = String.valueOf(tvDateValue.getText()).substring(14, 16);
                                edMinute.setText(valueMinute);
                            }
                        }
                    }
                } catch (ParseException ex) {

                    ex.printStackTrace();

                }
                calendar.setDate(c.getTimeInMillis());
                /**
                 * Control del evento Click del Button Limpiar
                 */

                Button btnLimpiar = (Button) popupView.findViewById(R.id.limpiar);
                btnLimpiar.setOnClickListener(new Button.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        tvDateValue.setText("");
                        popupWindow.dismiss();
                    }
                });

                /**
                 * Control del evento Click del Button Aceptar
                 */

                Button btnAceptar = (Button) popupView.findViewById(R.id.aceptar);
                btnAceptar.setOnClickListener(new Button.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (minuteOK &amp;&amp; hourOK) {
                            try {
                                String format = "MM-dd-yyyy";
                                SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);

                                final Calendar c = Calendar.getInstance();
                                tvDateValue.setText(sdf.format(calendar.getDate()).concat(" ").concat(edHour.getText().toString()).concat(":").concat(edMinute.getText().toString()));
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            popupWindow.dismiss();
                        } else if (minuteOK &amp;&amp; !hourOK) {
                            Toast.makeText(edMinute.getContext(), getString(R.string.validaMinutos),
                                    Toast.LENGTH_LONG).show();

                        } else if (!minuteOK &amp;&amp; hourOK) {
                            Toast.makeText(edHour.getContext(), getString(R.string.validaHora),
                                    Toast.LENGTH_LONG).show();

                        } else {
                            Toast.makeText(edMinute.getContext(), getString(R.string.validaHora) + "\n" + getString(R.string.validaMinutos),
                                    Toast.LENGTH_LONG).show();

                        }
                    }
                });

                // Validations
                edHour.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

                    }

                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {

                    }

                    @Override
                    public void afterTextChanged(Editable editable) {

                        if (edHour.getText() != null &amp;&amp;
                                edHour.getText().toString().length() &gt; 0 &amp;&amp;
                                (Double.valueOf(edHour.getText().toString())  23)) {

                            hourOK = false;
                            Toast.makeText(edHour.getContext(), getString(R.string.validaHora),
                                    Toast.LENGTH_LONG).show();
                        } else {
                            hourOK = true;
                        }
                    }
                });

                edMinute.addTextChangedListener(new TextWatcher() {
                    @Override
                    public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {

                    }

                    @Override
                    public void onTextChanged(CharSequence charSequence, int i, int i2, int i3) {

                    }

                    @Override
                    public void afterTextChanged(Editable editable) {

                        if (edMinute.getText() != null &amp;&amp;
                                edMinute.getText().toString().length() &gt; 0 &amp;&amp;
                                (Double.valueOf(edMinute.getText().toString())  59)) {
                            minuteOK = false;
                            Toast.makeText(edMinute.getContext(), getString(R.string.validaMinutos),
                                    Toast.LENGTH_LONG).show();
                        } else {
                            minuteOK = true;
                        }
                    }
                });

            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

}

Al informar una valor incorrecto para la hora se mostrará el siguiente mensaje:
Validar hora

En el caso de que el valor de los minutos sean incorrectos se mostrará el siguiente mensaje:
Validar minutos

Y si al pulsar sobre el botón aceptar no se han solucionado los problemas se mostrará el mensaje y no se permitirá salir de la ventana popup:
Aceptar con valores no validos

En el caso de que los valores sean validos, la información seleccionada se muestra en la pantalla inicial:
Fecha correcta

Dentro del código de la clase MainActivity se está utilizando el método setShownWeekCount del CalendarView. Al usar este método se ha tenido que incrementar la versión mínima de complicación a la 16. Para incrementarla hemos modificado el fichero build.gradle del proyecto.
build.gradle:

apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 16
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile 'com.android.support:appcompat-v7:19.+'
    compile fileTree(dir: 'libs', include: ['*.jar'])
}

Ahora tenemos nuestra ventana popup controlada por nosotros y ya hemos empezado a incluir validaciones a nuestros campos.

Anuncios
  1. No trackbacks yet.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: