En el capítulo anterior trabajamos con el DatePicker un componente que nos permitía trabajar con fechas de una forma muy sencilla. En este capítulo aprenderemos a usar el TimePicker, otro componente muy similar al anterior pero para la gestión de horas.

TimePicker en Kotlin

Este componente mostrará un diálogo flotante donde aparecerá un reloj que nos permitirá elegir la hora y los minutos.

ejemplo timepicker en kotlin
Ejemplo timePicker.

El funcionamiento de este capítulo es muy similar al capítulo anterior, por lo que iré más directo y si hay algo que no entendiste al 100% puedes echar un vistazo al capítulo 26 – DatePicker en Kotlin.

Let’s code

Tienes dos opciones ahora mismo, si has hecho el capítulo anterior, vamos a seguir con ese proyecto, y si no lo has hecho puedes crear un proyecto desde cero sin problema (con empty activity).

Yo usaré el layout del capítulo anterior y simplemente meteré un editText nuevo.

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_margin="24dp"
        android:text="Reserva en Restaurante Aris"
        android:textSize="24sp"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/etDate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="24dp"
        android:clickable="false"
        android:focusable="false"
        android:hint="¿Cuándo quieres ir?"/>

    <EditText
        android:id="@+id/etTime"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="24dp"
        android:clickable="false"
        android:focusable="false"
        android:hint="¿A qué hora?"/>

</LinearLayout>

Haciendo un breve repaso por el código, se trata de un linearLayout vertical, que tiene un textView que es el título y luego dos editText, uno el que gestiona el datePicker del capítulo anterior y el nuevo, etTime que se encargará de controlar el timePicker que hagamos. Recuerda, los editText deben tener el atributo clickable y focusable a false, para evitar que el usuario pueda escribir en dicho campo.

Volvemos al MainActivity donde añadiremos un listener al componente etTime.

  override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        etTime.setOnClickListener { showTimePickerDialog() }
    }

Cada vez que se pulse el editText, este llamará a la función showTimePickerDialog() que todavía no ha sido creada. La crearemos pero la dejaremos vacía por ahora.

private fun showTimePickerDialog() {
    }

Ahora iremos a la ruta de nuestro fichero, para ello haremos click en el botón lateral de la izquierda project. Una vez nos salga la ruta del proyecto haremos click en el icono del circulo para que nos lleve directamente a dónde estamos.

Ruta de nuestra clase.

También puedes ir siguiendo la ruta de las carpetas hasta llegar al fichero que por defecto debería ser app>src>main>java>com>nombreDeTuPaquete>MainActivity. Justo en la carpeta anterior hacemos click derecho y le damos a new>Kotlin Class/File. Seleccionaremos una clase y la llamaremos TimePickerFragment.

crear clases en kotlin en android studio
Creando la clase TimePickerFragment.

Una vez creada nuestra clase tendremos que añadirle como parámetro de entrada un listener, es decir, le pasaremos la posibilidad de ejecutar una función de la clase MainActivity, pasándole un parámetro, en concreto una String que será la hora seleccionada.

class TimePickerFragment(val listener:(String) -> Unit)

También la clase deberá extender de DialogFragment() e implementar el listener TimePickerDialog.OnTimeSetListener, que será la función que se ejecute cuando el usuario seleccione una hora. Nuestra clase quedará así.

class TimePickerFragment(val listener:(String) -> Unit) : DialogFragment(), TimePickerDialog.OnTimeSetListener {
}

La clase nos dará un error, hemos implementado un listener pero no hemos añadido su método, así que tenemos que añadir la función onTimeSet().

 override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
        listener("$hourOfDay:$minute")
    }

Se trata de un método que estamos implementando, que se llamará cuando el usuario seleccione una hora y nos devolverá la hora y los minutos por separado. En en ese momento en el que llamaremos a nuestro listener y le pasaremos una String formateando los dos Int que recibimos, añadiendo dos puntos entre ellos como solemos visualizar la hora.

Ahora tendremos que añadir el método que cree el dialog de tipo time.

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val c = Calendar.getInstance()
        val hour = c.get(Calendar.HOUR_OF_DAY)
        val minute = c.get(Calendar.MINUTE)
        val picker = TimePickerDialog(activity as Context, this, hour, minute, true)
        return picker
    }

Hemos creado un objeto de tipo Calendar, al cual con la función get() le pediremos la hora actual y los minutos. Fíjate bien de poner HOUR_OF_DAY en lugar de HOUR solamente. Luego creamos un objeto de tipo TimePickerDialog que recibe por parámetro el contexto, el listener que hemos implementado en nuestra clase (por eso solo hay que poner this), las horas, los minutos y luego tenemos la opción de mostrar dos calendarios, uno que muestre las 24 horas y otro que no.

Si ponemos el valor true al final, estamos activando la variable is24HourView, que mostrará las 24 horas en el reloj, si lo ponemos a false, solo aparecerán las 12 horas pero con una selección de AM o PM.

is24HourView variable a true
Variable is24HourView a true
is24HourView variable a false
Variable is24HourView a false

Aunque el diseño sea parecido, la respuesta es exactamente la misma, así que puedes usar el que prefieras.

Volvamos ahora al MainActivity, donde tendremos que completar la función showTimePickerDialog()

private fun showTimePickerDialog() {
        val timePicker = TimePickerFragment { onTimeSelected(it) }
        timePicker.show(supportFragmentManager, "timePicker")
    }

Esta función será la encargada de crear una instancia de TimePickerFragment y le pasaremos por parámetro una nueva función llamada onTimeSelected(), la cual recibirá una String, la que devolverá la clase TimePickerFragment al seleccionar una hora. Como solo devuelve un valor podemos poner directamente it que será la String. La segunda línea llama al método show() que mostrará el diálogo.

Para terminar nos queda crear la función onTimeSelected(), este método se encargará de asignar el valor de la String en el editText que creamos al principio, etTime.

 private fun onTimeSelected(time: String) {
        etTime.setText("Reserva para las $time")
    }

Cambiando colores en el TimePicker

Modificar el color de nuestro timePicker es exáctamente igual que para el datePicker del capítulo anterior. Iremos al fichero styles.xml, app>src>main>res>values>styles.xml.

Una vez dentro crearemos un nuevo theme llamado PickerTheme, que deberá tener de padre a android:Theme.Material.Light.Dialog

    <style name="PickerTheme" parent="android:Theme.Material.Light.Dialog">
        <item name="android:colorAccent">#FFA726</item>
    </style>

Dentro hemos definido el atributo colorAccent, que define el color principal del dialog.

Volvemos a TimePickerFragment y cuando creamos el objeto picker de tipo TimePickerDialog, añadimos un parámetro más en la segunda posición que será la ruta del estilo que hemos creado R.styles.PickerTheme. El método completo quedaría así.

  override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val c = Calendar.getInstance()
        val hour = c.get(Calendar.HOUR_OF_DAY)
        val minute = c.get(Calendar.MINUTE)
        val picker =
            TimePickerDialog(activity as Context, R.style.PickerTheme, this, hour, minute, false)
        return picker
    }

Si volvemos a ejecutar veremos que los colores han cambiado.

TimePicker en Kotlin android studio tutorial
Ejemplo final timePicker con colores personalizados.