android - 是否可以向 MaterialDateRange Picker 添加页脚?

标签 android calendar material-design material-components-android

我很确定这是不可能的,但我只是想在使用第 3 方库之前检查一下。 DatePicker 并不能真正让您自定义 UI,它基本上是一个全屏 DialogFragment,因此在上方或下方(甚至在顶部)放置某些内容似乎不是一种选择。

我的日历目前是这样的:

enter image description here

但我希望它看起来像这个底部有页脚的设计文档。如果您有任何想法,请告诉我,因为我不在其中。谢谢!

enter image description here

   val builder = MaterialDatePicker.Builder.dateRangePicker()
      .setTheme(R.style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen)
      .setCalendarConstraints(
        CalendarConstraints.Builder()
          .setStart(Date().time)
          .setEnd(oneYearFrom().time)
          .setValidator(AvailabilityValidator(it.unavailableDays)).build()
      )
    builder.setInputMode(MaterialDatePicker.INPUT_MODE_CALENDAR)
    builder.build().show(requireActivity().supportFragmentManager, TAG_DATE_RANGE_PICKER)

最佳答案

MaterialDateRangePicker 添加页脚的唯一方法是访问 Picker Root View ,从那里您可以找到 Picker FrameLayout Container(Id app:id/mtrl_calendar_frame) 并访问其 subview Vertical LinearLayout Container 其中包含三个子项:(一个 Days-GridView,一个Separator-ViewRecyclerView) 在垂直方向。您想要的是在 RecyclerView 下方添加一个页脚。因为父级是 LinearLayout,所以您可以将 weight 属性添加到其所有子级,使其成为 weight=0 除了 RecyclerView(呈现月份) 为 weight=1 以获得所有剩余空间。

要访问 Picker Root View ,您必须观察 MaterialDatePicker (DialogFragment) 生命周期并在 DialogFragment 的 onStart() 中添加页脚 View 。为此,您可以使用 DefaultLifecycleObserver

下面是添加页脚 View 的完整工作示例:

private fun showRangeDatePicker() {

    //initialize dateRangePicker
    val builder = MaterialDatePicker.Builder.dateRangePicker()
    builder.setTheme(R.style.ThemeOverlay_MaterialComponents_MaterialCalendar_Fullscreen)

    //set CalendarConstraints
    val constraintsBuilder = CalendarConstraints.Builder()
    val c: Calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"))
    constraintsBuilder.setStart(c.getTimeInMillis())
    c.add(Calendar.YEAR, 1)
    constraintsBuilder.setEnd(c.getTimeInMillis())
    builder.setCalendarConstraints(constraintsBuilder.build())

    //set InputMode and Title
    builder.setInputMode(MaterialDatePicker.INPUT_MODE_CALENDAR)
    builder.setTitleText("Pick dates")

    //get MaterialDatePicker instance and set a lifecycle Observer to listen for DialogFragment lifecycle
    //DefaultLifecycleObserver needs androidx.appcompat:appcompat:1.4.0 and add the FooterView in onStart of DialogFragment
    val picker: MaterialDatePicker<*> = builder.build()
    picker.lifecycle.addObserver(object : DefaultLifecycleObserver
    {
        override fun onCreate(owner: LifecycleOwner) {
        }

        override fun onStart(owner: LifecycleOwner) {
            //add footerView in onStart of DialogFragment so you can access the picker.view
            addMyFooterView(picker)
        }

        override fun onResume(owner: LifecycleOwner) {
        }

        override fun onDestroy(owner: LifecycleOwner) {
            //remove Lifecycle Observer
            picker.lifecycle.removeObserver(this)
        }
    })
    picker.show(supportFragmentManager, picker.toString())
}

private fun addMyFooterView(picker: MaterialDatePicker<*>) {

    //get the MaterialDatePicker root View
    val rootView = picker.view as LinearLayout
    //find the Picker FrameLayout Container with ID: app:id/mtrl_calendar_frame
    val frameLayout = rootView.findViewById<FrameLayout>(resources.getIdentifier("mtrl_calendar_frame", "id", packageName))
    //and get the Picker LinearLayout Container (which contains of 3 children: Days-GridView, Separator-View and a RecyclerView)
    val linearContainer = frameLayout.getChildAt(0) as LinearLayout

    //for each child in Vertical LinearLayout Container set the weight to RecyclerView to 1 and 0 to all others.
    //(This is necessary before adding the footerView to distribute correctly each children Height)
    for (i in 0 until linearContainer.childCount) {
        val v = linearContainer.getChildAt(i)
        val params = v.layoutParams as LinearLayout.LayoutParams
        params.weight = if (v is RecyclerView) 1f else 0f
        v.layoutParams = params
    }

    //and finally add the 4th child in the above linearContainer to be the FooterView
    val myFooterView = layoutInflater.inflate(R.layout.footer_layout, null)
    val myFooterViewHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50f, resources.displayMetrics).toInt()
    myFooterView.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, myFooterViewHeight, 0f)
    myFooterView.setBackgroundColor(Color.WHITE)
    linearContainer.addView(myFooterView)

    //set any FooterView click listeners
    myFooterView.findViewById<View>(R.id.textView2).setOnClickListener {}
}

footer_layout 是您自定义的页脚 xml 布局,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp">

    <View
        android:id="@+id/separatorView"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_alignParentTop="true"
        android:background="@android:color/darker_gray"/>

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp"
        android:textStyle="bold"
        android:layout_marginEnd="10dp"
        android:layout_centerVertical="true"
        android:layout_alignParentStart="true"
        android:text="Match exact dates" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp"
        android:textStyle="normal"
        android:layout_marginEnd="10dp"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@+id/textView1"
        android:text="±1 day" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="15sp"
        android:textStyle="normal"
        android:layout_marginEnd="10dp"
        android:layout_centerVertical="true"
        android:layout_toEndOf="@+id/textView2"
        android:text="±3 days" />

</RelativeLayout>

结果:

date_picker_dialog

关于android - 是否可以向 MaterialDateRange Picker 添加页脚?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70149110/

相关文章:

android - 在 Android 上从图库中选择图像时出现权限问题

javascript - 如何创建两个日历并使用 JavaScript 将它们链接在一起

android - 从日历获取事件的问题

css - Angular Material 将垫子墨水条旋转到垂直位置

css - 设置 SVG Material Design 图标的背景颜色

html - 如何使用伪 CSS 过渡更改事件切换按钮的 CSS

android - 如何创建一个 ListPreference 对话框以在非偏好 Activity 中显示

Android 打瞌睡模式 - 蓝牙

android - 函数无法使用协程 block 返回项目

calendar - Outlook 2013 邀请不显示嵌入附件 - 文本/日历;method=REQUEST