Nota: este artículo se basó en la versión Material Components 1.2.0-beta01 a partir de 1 de junio de 2020 .



En mis tres años y medio trabajando en un pequeño equipo de Android en HASHTAGS, una de las principales cosas que me motiva a trabajar todos los días es la libertad y la confianza de nuestra empresa para abordar un problema de la forma que consideremos mejor.



La libertad de investigar y explorar muchas soluciones diferentes a un problema que consideramos necesario, al tiempo que contamos con un marco de tiempo para entregar actualizaciones de productos, nos permite encontrar la mejor solución tanto para nuestros clientes como para nuestro software.

Uno de esos desafíos implicó la creación de un componente de interfaz de usuario para nuestra nueva función de informes móviles. Este nuevo componente fue un selector de meses, lo que permitió a nuestros usuarios establecer un rango de fechas para un informe de análisis.

El lugar de partida que elegimos fue el existente Biblioteca de componentes de materiales . En lugar de comenzar desde cero, esta biblioteca se mantiene activamente y se alinea con las especificaciones de materiales. Con esta biblioteca como base, probablemente podríamos reducir la cantidad de lógica que tendríamos que escribir nosotros mismos.

En este artículo, cubriré cómo abordamos este proceso, algunos factores únicos en la creación de la aplicación Sprout para Android, algunos 'errores' que surgieron (y se solucionaron) a lo largo del camino y qué saber si estás trabajando en un proyecto similar.

Introducción

Los componentes de material de Android 1.1.0 Lanzamiento introdujo un nuevo componente de interfaz de usuario de selector de fecha. Una de las bienvenidas adiciones de este nuevo MaterialDatePicker sobre AppCompat CalendarView es la capacidad de seleccionar un rango de fechas usando una vista de calendario o un campo de entrada de texto.



El antiguo AppCompat CalendarView no era muy flexible. Era un buen componente para el caso de uso limitado que estaba destinado a resolver; es decir, seleccionar una fecha única y fechas mínimas y máximas opcionales para especificar un límite de rango de fechas permitido.

El nuevo MaterialDatePicker se creó con más flexibilidad para permitir el uso de una funcionalidad ampliada de comportamiento. Funciona a través de una serie de interfaces que se pueden implementar para ajustar y modificar el comportamiento del selector.

Esta modificación de comportamiento se realiza en tiempo de ejecución mediante un conjunto de funciones de patrón de constructor en MaterialDatePicker.Builder clase.



Esto significa que podemos extender el comportamiento base de este MaterialDatePicker a través de componentes de interfaz componibles.

Nota: Aunque hay varios componentes diferentes, MaterialDatePicker utiliza, en este artículo cubriremos únicamente el componente de selección de fecha.


833 número de ángel amor

Selector de intervalo de fechas

El equipo de HASHTAGS Android estaba en el proceso de crear nuestra sección de informes de análisis.

Esta nueva sección permitiría a nuestros usuarios seleccionar un conjunto de filtros y un conjunto de intervalos de fechas que cubriría el informe.

El MaterialDatePicker vino con algunos componentes prediseñados que pudimos aprovechar para lograr nuestro caso de uso.

Para nuestro caso más común, que permite a un usuario seleccionar un rango de fechas, el MaterialDatePicker bastaría:

Con este bloque de código, obtenemos un Selector de fecha que permite a los usuarios seleccionar un rango de fechas.

Selector de fecha mensual

Uno de los informes HASHTAGS que tiene una selección de fecha más exclusiva es el Informe de tendencias de Twitter.

Este informe se diferencia de los demás en que, en lugar de permitir cualquier tipo de rango de fechas, aplica una selección de un solo mes, lo que significa que un usuario solo puede seleccionar marzo de 2020 frente al 3 de marzo al 16 de marzo de 2020.

Nuestra aplicación web maneja esto usando un campo de formulario desplegable:

El MaterialDatePicker no tiene una forma de hacer cumplir dicha restricción con el Selector de rango de fechas de material prediseñado que se discutió en la sección anterior. Afortunadamente, MaterialDatePicker se creó con partes componibles que nos permiten expandir el comportamiento predeterminado para nuestro caso de uso particular.

Comportamiento de selección de fecha

El MaterialDatePicker aprovecha un DateSelector como la interfaz utilizada para la lógica de selección del selector.

Desde el Javadoc:

“Interfaz para usuarios de {@link MaterialCalendar} para controlar cómo se muestra el calendario y devuelve las selecciones ... '

Notará que el MaterialDatePicker.Builder.dateRangePicker() devuelve una instancia de constructor de RangeDateSelector, que usamos en el ejemplo anterior.

Esta clase es un selector prediseñado que implementa DateSelector.

Lluvia de ideas sobre un comportamiento de selección de fecha mensual

Para nuestro caso de uso, queríamos una forma de que nuestros usuarios seleccionaran un mes completo como un rango de fechas seleccionado; p.ej. Mayo de 2020, abril de 2020, etc.

Pensamos que el preconstruido RangeDateSelector mencionado anteriormente nos llevó la mayor parte del camino allí. El componente permitía al usuario seleccionar un rango de fechas y hacer cumplir una atado .

Lo único que faltaba era una forma de hacer cumplir una selección para seleccionar automáticamente todo el mes. El comportamiento predeterminado de RangeDateSelector hace que el usuario seleccione una fecha de inicio y una fecha de finalización.

Queríamos un comportamiento para que cuando un usuario seleccionara un día del mes, el selector seleccionara automáticamente el mes completo como rango de fechas.

La solución que decidimos fue extender el RangeDateSelector y luego anule el comportamiento de selección del día para seleccionar automáticamente todo el mes.

Afortunadamente, hay una función que podemos anular desde la interfaz DateSelector llamado: select(selection: Long).

Esta función se invocará cuando un usuario seleccione un día en el selector, con el día seleccionado transcurrido en milisegundos UTC desde la época.

Implementar un comportamiento de selección de fecha mensual

La implementación resultó ser la parte más simple, ya que tenemos una función clara que podemos anular para obtener el comportamiento que queremos.

La lógica básica será esta:

  1. El usuario selecciona un día.
  2. El select() La función se invoca con el día seleccionado en un Largo UTC milisegundos desde la época.
  3. Encuentre el primer y último día del mes a partir del día que nos pasó.
  4. Llamar a super.select(1st of month) & super.select(last day of month)
  5. El comportamiento de los padres de RangeDateSelector debería funcionar como se esperaba y seleccione el mes como intervalo de fechas.

Poniendolo todo junto

Ahora que tenemos nuestro Custom MonthRangeDateSelector, podemos configurar nuestro MaterialDatePicker.

Para llevar el ejemplo más allá, podemos procesar el resultado de la selección así:

El resultado se verá así:

Gotchas

Solo había un problema importante que dificultaba llegar a esta solución.

Los componentes principales utilizados para construir nuestro MonthRangeDateSelector fueron la clase RangeDateSelector y la interfaz DateSelector. La versión de la biblioteca utilizada en este artículo (1.2.0-beta01) restringió la visibilidad de estos dos archivos, para desalentar su extensión o implementación.

Como resultado, aunque pudimos compilar con éxito nuestro nuevo MonthRangeDateSelector, el compilador mostró una advertencia muy aterradora para disuadirnos de hacerlo:

Una forma de ocultar esta advertencia del compilador es agregar un @Suppress('RestrictedApi') al igual que:

Esta experiencia ilustra cómo, a pesar de que la biblioteca de componentes de materiales ha proporcionado algunos componentes nuevos excelentes a la comunidad de desarrolladores de Android, todavía es un trabajo en progreso.

Una gran parte de esta biblioteca es la apertura a los comentarios de la comunidad de Android. Después de descubrir esta restricción de visibilidad del componente, abrí un asunto en el Proyecto Github, e incluso abrió un PR para abordarlo de inmediato.

Este circuito de comentarios abierto entre el equipo de componentes de materiales y la comunidad de Android genera una gran colaboración y resultados para todos.

Conclusión

El nuevo MaterialDatePicker tiene una excelente funcionalidad lista para usar que probablemente cubrirá la mayoría de los casos de uso de selección de fecha.

Sin embargo, la mejor parte de algo como AppCompat CalendarView es que está construido de forma componible. Por lo tanto, se puede extender y modificar fácilmente para casos de uso específicos, mientras que sería mucho más difícil lograr tales cosas en el CalendarView.

Gracias especiales

Me gustaría destacar a algunas personas que ayudaron a revisar este artículo:

Compartir Con Tus Amigos: