注:本文基于Material Components版本1.2.0-beta012020年6月1日

在我为Sprout Social的一个小型Android团队工作的3年半时间里,激励我每天去工作的主要因素之一是公司给予我的自由爱游戏体育官网首页爱游戏app体育官方和信任,我们可以用我们认为最好的方式来解决问题。

对于我们认为必要的问题,我们可以自由地研究和探索许多不同的解决方案,同时考虑到交付产品更新的时间框架,爱游戏体育入口登录这使我们能够为客户和软件找到最佳解决方案。爱游戏全站下载

其中一个挑战涉及为我们新的Mobile Reporting功能构建UI组件。这个新组件是一个月份选择器,它允许我们的用户为分析报告确定日期范围。

我们选择的起始点是既存点材料组件库。而不是从头开始,这个库被积极维护,并与材料规范保持一致。有了这个库作为基础,我们可以减少必须自己编写的逻辑量。

在本文中,我将介绍我们如何处理这个过程,为Sprout Android应用程序构建的一些独特因素,在此过程中出现的一些“陷阱”(并已修复),以及如果您正在从事类似的项目,应该知道什么。爱游戏体育官网首页

介绍

Android材质组件1.1.0版本引入了一个新的日期选择器UI组件。这个新功能的一个受欢迎的补充MaterialDatePicker通过AppCompatCalendarView是使用日历视图或文本输入字段选择日期范围的能力。

旧的AppCompat CalendarView不是很灵活。对于它想要解决的有限用例来说,它是一个很好的组件;也就是说,选择单个日期和可选的最小和最大日期来指定允许的日期范围界限。

新的MaterialDatePicker具有更大的灵活性,允许使用扩展的行为功能。它通过一系列接口工作,可以实现这些接口来调整和修改选择器的行为。

类上的一组构建器模式函数在运行时完成此行为修改MaterialDatePicker。构建器类。

这意味着我们可以扩展它的基本行为MaterialDatePicker通过可组合的接口组件。

注意:虽然有许多不同的组件MaterialDatePicker在本文中,我们将只讨论日期选择组件。

日期范围选择器

Spro爱游戏体育官网首页爱游戏app体育官方ut Social Android团队正在构建我们的分析报告部分。

这个新的部分将允许我们的用户选择一组过滤器和一组报告将涵盖的日期范围。

MaterialDatePicker附带了一些预构建的组件,我们可以利用它们来完成我们的用例。

对于我们最常见的情况,允许用户选择日期范围,即预先构建的MaterialDatePicker就足够了:

通过这个代码块,我们得到一个Date Picker,它允许用户选择一个日期范围。

每月日期选择器

其中一个有更独特的日期爱游戏体育官网首页爱游戏app体育官方选择的社交报告是Twitter趋势报告。

此报告与其他报告的不同之处在于,它不允许任何类型的日期范围,而是强制选择单个月,这意味着用户只能选择2020年3月与2020年3月3日至3月16日。

我们的web应用程序通过使用下拉表单字段来处理这个问题:

MaterialDatePicker没有办法使用上一节中讨论的预构建的Material Date Range Picker来强制执行这样的限制。幸运的是,MaterialDatePicker是用可组合的部件构建的,这些部件允许我们扩展特定用例的默认行为。

日期选择行为

MaterialDatePicker利用一个DateSelector作为用于选择器的选择逻辑的接口。

来自Javadoc:

的用户界面{@link MaterialCalendar <年代>}来控制日历显示和返回选择的方式……”

你会注意到MaterialDatePicker.Builder.dateRangePicker ()的构造器实例RangeDateSelector,我们在上面的例子中使用了它。

这个类是一个预构建的选择器,它实现DateSelector

头脑风暴每月的日期选择行为

对于我们的用例,我们想要一种方法让我们的用户选择一个完整的月作为选择的日期范围;例如2020年5月、2020年4月等。

我们认为预建的RangeDateSelector上面提到的让我们有了大部分的方法。该组件允许用户选择日期范围并强制执行[下,上]界

唯一缺少的是一种强制选择以自动选择整个月的方法。的默认行为。RangeDateSelector让用户选择开始日期和结束日期。

我们想要这样一种行为,当用户选择一个月中的某一天时,选择器将自动选择整个月作为日期范围。

我们决定的解决方案是扩展RangeDateSelector然后重写日期选择行为以自动选择整个月。

幸运的是,我们可以从接口重写一个函数DateSelector被称为:选择(选择:长)

当用户在选择器中选择日期时,将调用此函数,所选日期以UTC毫秒为单位从epoch传递。

实现每月日期选择行为

实现是最简单的部分,因为我们有一个清晰的函数,我们可以重写它来获得我们想要的行为。

基本逻辑是这样的:

  1. 用户选择一天。
  2. select ()函数中使用所选日期调用从epoch开始的UTC毫秒数。
  3. 从传递给我们的某一天开始,找出该月的第一天和最后一天。
  4. 打电话给…超级。选择(每月1日)&超级。选择(每月的最后一天)
  5. 父母的行为RangeDateSelector应按预期工作,并选择月份作为日期范围。

把它们放在一起

现在我们有了CustomMonthRangeDateSelector我们可以建立我们的MaterialDatePicker

为了进一步扩展示例,我们可以这样处理选择的结果:

结果看起来像这样:

陷阱

只有一个主要问题使我们难以达成这个解决方案。

用于构建我们的MonthRangeDateSelector我们是班级RangeDateSelector还有界面DateSelector。本文使用的库版本(1.2.0-beta01)限制了这两个文件的可见性,以阻止扩展或实现它们。

结果,尽管我们可以成功地编译新的MonthRangeDateSelector,编译器确实显示了一个非常可怕的警告来阻止我们这样做:

隐藏此编译器警告的一种方法是添加@Suppress(“RestrictedApi”)像这样:

这个经验说明,尽管Material Components Library已经为Android开发者社区提供了一些很棒的新组件,但它仍然是一个正在进行的工作。

这个库的一个重要部分是对来自Android社区的反馈的开放性!发现这个组件可见性限制后,我打开了一个问题在Github项目上,甚至打开了一个公关马上解决这个问题。

材料组件团队和Android社区之间的这种开放反馈循环为每个人带来了良好的合作和结果。

结论

MaterialDatePicker有一些很好的开箱即用的功能,可能会覆盖大多数的日期选择用例。

然而,与AppCompat CalendarView相比,它最好的部分是它是以可组合的方式构建的。因此,它可以很容易地针对特定的用例进行扩展和修改,而在java语言中完成这样的事情要困难得多CalendarView

特别感谢

我想强调一些帮助同行评议这篇文章的人: