材料日期选择器自定义样式

13
我使用了谷歌材料设计的日期选择器,并结合这个库。

implementation 'com.google.android.material:material:1.2.0-alpha02'

这是我的代码。
     MaterialDatePicker.Builder<Pair<Long, Long>> builder =
            MaterialDatePicker.Builder.dateRangePicker();

    CalendarConstraints.Builder constraintsBuilder = new CalendarConstraints.Builder();
    builder.setCalendarConstraints(constraintsBuilder.build());
    MaterialDatePicker<Pair<Long,Long>> picker = builder.build();
    assert getFragmentManager() != null;
    picker.show(getFragmentManager(), picker.toString());
我想自定义对话框选择器中的文本字段,使对话框不全屏等等... 我该如何进行所有这些修改?

输入图像描述


改变文本字段是什么意思? - Gabriele Mariotti
@GabrieleMariotti 更改保存文本、开始日期和结束日期文本。 - zakaria
5个回答

30

关于全屏

范围选择器应覆盖整个屏幕(默认为单日期对话框,时间范围选择器为全屏)。 但是您可以在样式中更改此行为。

您可以使用setTheme方法应用主题覆盖:

//To apply a dialog
builder.setTheme(R.style.ThemeOverlay_MaterialComponents_MaterialCalendar);
//To apply the fullscreen:
builder.setTheme(R.style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen);

注意: 它需要至少版本 1.2.0-alpha01

作为替代方案,您可以在应用程序主题中添加 materialCalendarFullscreenTheme 属性。

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
   <item name="materialCalendarFullscreenTheme">@style/CustomThemeOverlay_MaterialCalendar_Fullscreen</item>
</style>

其中:

  <style name="CustomThemeOverlay_MaterialCalendar_Fullscreen"
      parent="@style/ThemeOverlay.MaterialComponents.MaterialCalendar.Fullscreen">
    <item name="materialCalendarStyle">@style/Custom_MaterialCalendar.Fullscreen</item>
  </style>

您可以使用android:windowFullscreen属性覆盖该值:

  <style name="Custom_MaterialCalendar.Fullscreen"
      parent="@style/Widget.MaterialComponents.MaterialCalendar.Fullscreen">
    <item name="android:windowFullscreen">false</item>
  </style>

这里输入图片描述


关于字符串
目前没有更改字符串的方法。
唯一现有的方法是使用 builder.setTitleText 更改标题。

但是,您可以在项目中覆盖所有现有的字符串,但此解决方法可能无法在以后的版本中运行。例如:

  <string name="mtrl_picker_save" description="Confirms the selection [CHAR_LIMIT=12]">....</string>
  <string name="mtrl_picker_text_input_date_range_start_hint" description="Label for the start date in a range selected by the user [CHAR_LIMIT=60]">...</string>
  <string name="mtrl_picker_text_input_date_range_end_hint" description="Label for the end date in a range selected by the user [CHAR_LIMIT=60]">...</string>

图片描述输入在此处

您可以在1.2.0-alpha02中使用的材料日历中找到所有字符串


非常感谢您的回复,禁用全屏功能非常有效。但是关于在我的代码中覆盖字符串,我该怎么做呢? - zakaria
@zakaria 只需在您的 strings.xml 文件中添加要覆盖的项目,就像上面的示例一样。 - Gabriele Mariotti
是的,我已经修复了。只需将字符串复制粘贴到您的字符串文件中并更改值,感谢您的帮助,现在它可以工作了。 - zakaria

9

基本上,您应该玩弄样式。在您的AppTheme中添加一个项目materialCalendarTheme,它是继承父级ThemeOverlay.MaterialComponents.MaterialCalendar 的自定义样式,并更改样式。

  1. 更改文本字段 - 调用MaterialDatePicker.Builder函数setTitleText()
  2. 使对话框不全屏 - 对于日期范围选择器,您无法更改它,默认情况下它是全屏的,文档中也说明了这一点

移动日期范围选择器允许选择一段时间范围。它们覆盖整个屏幕。

这是文档 https://material.io/components/pickers

以下是我如何调整一些颜色以匹配我的主题:

<style name="AppTheme" parent="Theme.MaterialComponents.Light">
    <item name="materialCalendarTheme">@style/ThemeMaterialCalendar</item>
</style>

<style name="ThemeMaterialCalendar" parent="ThemeOverlay.MaterialComponents.MaterialCalendar">
    <item name="buttonBarPositiveButtonStyle">@style/ThemeMaterialCalendarButton</item>
    <item name="buttonBarNegativeButtonStyle">@style/ThemeMaterialCalendarButton</item>
    <item name="materialButtonStyle">@style/ThemeMaterialCalendarTextButton</item>
</style>

<style name="ThemeMaterialCalendarButton" parent="Widget.MaterialComponents.Button.TextButton.Dialog">
    <item name="android:textColor">?themeTextColorPrimary</item>
</style>

<style name="ThemeMaterialCalendarTextButton" parent="Widget.MaterialComponents.Button.TextButton.Dialog.Flush">
    <item name="android:textColor">?themeTextColorPrimary</item>
    <item name="iconTint">?themeTextColorPrimary</item>
</style>

当我在ThemeMaterialCalendarButton中设置android:textColor时,应用程序会崩溃。 - CoolMind

5

切换全屏和对话框版本可以像这样简单:

全屏模式

val picker = MaterialDatePicker.Builder.dateRangePicker().setTheme(R.style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen).build()

对话框:

val picker = MaterialDatePicker.Builder.dateRangePicker().setTheme(R.style.ThemeOverlay_MaterialComponents_MaterialCalendar).build()

它可以工作。我不得不将库升级到'com.google.android.material:material:1.2.0-alpha06',从1.1.0版本升级,这样R.style....就不会被Lint标记为私有属性了。 - CoolMind
我们可以为DatePicker片段应用自己的“layout”文件吗? - IgorGanapolsky

1

虽然发布的答案完全有效,但似乎没有必要全局设置materialCalendarTheme - 您可以通过MaterialDatePicker.BuildersetTheme(int themeResId)方法将其设置为。以下是他们在Material Design Catalog App中的示例。

val datePicker = MaterialDatePicker.Builder.dateRangePicker().apply {
    context?.resolveOrNull(R.attr.materialCalendarTheme)?.let {
        setTheme(it)
    }
    setCalendarConstraints(getConstraints())
    }.build()
// ...

resolveOrThrow辅助方法:

fun Context.resolveOrNull(@AttrRes attributeResId: Int): Int? {
    val typedValue = TypedValue()
    if (theme.resolveAttribute(attributeResId, typedValue, true)) {
        return typedValue.data
    }
    return null
}

这样,您的DatePicker对话框不会变成全屏,而是一个普通的对话框。


0
postfixNotation 给出的答案是正确的,但他忘记了提到样式可用的包名。我为此苦恼了大约30分钟,因为它不直接在R.style中可用...所以这里是答案,对于所有人来说都会起作用,如果有人遇到了同样的问题。

在全屏和对话框版本之间切换可以非常简单:

全屏

val picker = MaterialDatePicker.Builder.dateRangePicker().setTheme(com.google.android.material.R.style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen).build()

对话框:

val picker =  MaterialDatePicker.Builder.dateRangePicker().setTheme(com.google.android.material.R.style.ThemeOverlay_MaterialComponents_MaterialCalendar).build()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接