【问题标题】:Is it possible to add a footer to the MaterialDateRange Picker?是否可以向 Material DateRangePicker 添加页脚?
【发布时间】:2022-01-05 23:21:09
【问题描述】:

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

我的日历目前如下所示:

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

   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)

【问题讨论】:

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


    【解决方案1】:

    MaterialDateRangePicker 添加页脚的唯一方法是访问Picker 根视图,从那里您可以找到Picker FrameLayout Container(ID 为app:id/mtrl_calendar_frame)并访问其子视图@ 987654326@ 包含三个孩子:(Days-GridViewSeparator-ViewRecyclerView)在垂直方向。您想要的是在 RecyclerView 下方添加一个页脚。因为父级是 LinearLayout,所以您可以将 weight 属性添加到其所有子级,使其成为 weight=0,除了 RecyclerView(渲染月份)为 weight=1 以获取所有剩余空间。

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

    以下是添加页脚视图的完整示例:

    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>
    

    结果:

    【讨论】:

    • 这非常有效。谢谢!
    猜你喜欢
    • 2022-11-10
    • 2017-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-24
    相关资源
    最近更新 更多