Kotlin中DatePickerDialog选择日期后未更新TextView且未关闭的问题求助
问题:DatePickerDialog选择日期后未更新按钮文本也未关闭对话框?
我在Kotlin的Fragment里使用DatePickerDialog时遇到了麻烦:原本期望用户选择日期后,更新appointmentDateButton的文本并且自动关闭对话框,但实际情况是选完日期后,只有对话框自身的日期显示变化了,按钮文本没更新,对话框也一直停留在界面上。
以下是我的实现代码:
@AndroidEntryPoint class AppointmentListFragment : Fragment() { private var _binding: FragmentAppointmentListBinding? = null private val binding: FragmentAppointmentListBinding get() = _binding!! private val viewModel: AppointmentMainViewModel by viewModels() private val today = Calendar.getInstance() private val day = today.get(Calendar.DAY_OF_MONTH) private val month = today.get(Calendar.MONTH) + 1 private val year = today.get(Calendar.YEAR) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentAppointmentListBinding.inflate(inflater) setDateText( getString( R.string.date_placeholder, String.format("%02d", day), String.format("%02d", month), year ) ) binding.appointmentDateButton.setOnClickListener { val dpd = DatePickerDialog( it.context, { datePicker, y, m, d -> datePicker.minDate = System.currentTimeMillis() setDateText( getString( R.string.date_placeholder, String.format("%02d", d), String.format("%02d", m), y ) ) }, year, month, day ) dpd.show() } return binding.root } private fun setDateText(date: String) { binding.appointmentDateButton.text = date } }
请问我哪里没做到位?希望各位开发者能帮我找出问题所在!
解决方案:
你的代码有几个关键问题需要修正,我逐一说明:
- 忘记手动关闭对话框:
DatePickerDialog默认不会在用户选择日期后自动关闭,必须在回调里手动调用dpd.dismiss()才能触发关闭操作。 minDate设置位置错误:你把日期范围限制的代码写在了选择回调里,这时候用户已经完成选择,完全起不到限制作用。正确的做法是在dpd.show()之前设置,这样对话框打开时就会禁止选择今天之前的日期。- 月份参数的0-based问题:
DatePickerDialog的构造函数中,month参数是从0开始计数的(1月对应0,12月对应11),但你初始化时传入的是加1后的月份,导致初始显示月份错误;同时回调里直接用0-based的m格式化显示,会让显示的月份比实际选择的小1,需要改为m + 1。
修正后的完整代码:
@AndroidEntryPoint class AppointmentListFragment : Fragment() { private var _binding: FragmentAppointmentListBinding? = null private val binding: FragmentAppointmentListBinding get() = _binding!! private val viewModel: AppointmentMainViewModel by viewModels() private val today = Calendar.getInstance() private val day = today.get(Calendar.DAY_OF_MONTH) // 改为直接获取0-based的月份,初始化显示时再转成1-based private val month = today.get(Calendar.MONTH) private val year = today.get(Calendar.YEAR) override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = FragmentAppointmentListBinding.inflate(inflater) setDateText( getString( R.string.date_placeholder, String.format("%02d", day), String.format("%02d", month + 1), year ) ) binding.appointmentDateButton.setOnClickListener { val dpd = DatePickerDialog( requireContext(), // 用Fragment的requireContext()比it.context更可靠 { _, y, m, d -> // 格式化月份时转为1-based setDateText( getString( R.string.date_placeholder, String.format("%02d", d), String.format("%02d", m + 1), y ) ) // 手动关闭对话框 dpd.dismiss() }, year, month, day // 传入0-based的月份 ) // 在show之前设置最小日期,减1秒避免当天凌晨的边界问题 dpd.datePicker.minDate = System.currentTimeMillis() - 1000 dpd.show() } return binding.root } private fun setDateText(date: String) { binding.appointmentDateButton.text = date } }
内容的提问来源于stack exchange,提问作者YohDono
相关产品推荐
相关产品推荐

