Descubre Su Número De Ángel
Ingeniería en Sprout: creación de un selector de meses de Android
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:
- El usuario selecciona un día.
- El
select()
La función se invoca con el día seleccionado en un Largo UTC milisegundos desde la época. - Encuentre el primer y último día del mes a partir del día que nos pasó.
- Llamar a
super.select(1st of month)
&super.select(last day of month)
- 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:
- Nick Rout ( Github )
- Mike Wolfson ( Github )
- Ryan Phillips ( LinkedIn )
- Lucas Moellers ( Github )
- Con patel LinkedIn )
Compartir Con Tus Amigos: