单击其 24 小时版本时,TimePicker 错误地选择了同一时间的 12 小时版本

TimePicker incorrectly choosing 12 hour version of the same time when clicking on its 24 hour version

很奇怪。我知道。这是执行代码。

(编辑中的代码。)

一旦我 select 一个时间和日期,并再次执行相同的操作,之前的输出文本与这次输出文本不同。

请注意,用户设置为 24 小时格式。

第一次做:

这是第一次执行后的样子(忽略突出显示的 "person",这是联系人搜索机制的实现):

然后,又是同样的事情(我发誓这是我第二次这样做,它看起来可能是一样的):

但这是什么怪物?!

Toasts 确认我输入的是 24 小时 if 子句,所以我认为选择正确的日期格式是可以的。 (另请注意,如果它是 12 小时格式,AM/PM 会按照代码的建议存在,但输出中不存在)。

我不知道这怎么会发生。 SimpleDateFormat 是在使用之前实例化的,所以不可能在其他任何地方乱用它,所以我认为它不是来自 datePickerDialog.

任何 clues/suggestions/ideas?

编辑:根据要求,这是适配器代码。我是新来的所以请放轻松 :) 相关代码在fun setDateTime()


class ContactAdapter(
    private val context: Context,
    private val contact_name: String?,
    private val items: List<Contact>
) :
    RecyclerView.Adapter<ContactAdapter.ViewHolder>() {
    private val c = Calendar.getInstance()
    fun createDatePicker(onSetDate: (DatePicker, Int, Int, Int) -> Unit) = DatePickerDialog(
        context,
        onSetDate,
        c[Calendar.YEAR],
        c[Calendar.MONTH],
        c[Calendar.DAY_OF_MONTH]
    )

    fun createTimePicker(onSetTime: (TimePicker, Int, Int) -> Unit) = TimePickerDialog(
        context,
        onSetTime,
        c[Calendar.HOUR],
        c[Calendar.MINUTE],
        DateFormat.is24HourFormat(context)
    )

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {

        init {
            setupAddButton()
            setupGreetingTimeText()
        }

        private fun setDateTime() {
            val datePicker = createDatePicker { _, year, month, date ->
                c[Calendar.YEAR] = year
                c[Calendar.MONTH] = month
                c[Calendar.DAY_OF_MONTH] = date

                val timePicker = createTimePicker { _, hour, minute ->
                    c[Calendar.HOUR] = hour
                    c[Calendar.MINUTE] = minute
                    itemView.txtGreetingTime.text = if (DateFormat.is24HourFormat(context)) {
                        Toast.makeText(context, "Chose 24-hour clause", Toast.LENGTH_SHORT).show()
                        SimpleDateFormat(
                            "dd mmm, yyyy 'at' HH:mm",
                            Locale.getDefault()
                        ).format(c.time)
                    } else {
                        Toast.makeText(context, "Chose 12-hour clause", Toast.LENGTH_SHORT).show()
                        SimpleDateFormat(
                            "dd mmm, yyyy 'at' hh:mm aa",
                            Locale.getDefault()
                        ).format(c.time)
                    }
                }

                // Do time picking stuff
                timePicker.show()

            }
            // Do date picking stuff
            datePicker.show()

        }
        private fun setupAddButton() {
            itemView.addButton.setOnClickListener {
                println("Attempted call to ${itemView.contactPhone.text}")
                itemView.layoutTimingDetails.visibility =
                    if (itemView.layoutTimingDetails.visibility == View.VISIBLE) View.GONE else View.VISIBLE

            }
        }

        private fun setupGreetingTimeText() {
            itemView.txtGreetingTime.setOnClickListener {
                it.txtGreetingTime.text = dateTimeToString()
            }
        }

        fun setData(item: Contact, contact_name: String?) {
            itemView.contactName.text = item.name
            itemView.contactPhone.text = item.phone
            itemView.contactEmail.text = item.email

            if (contact_name != null)
                itemView.contactName.highlightBackground(contact_name, Color.YELLOW)
        }
    }

    override fun getItemCount(): Int = items.size
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder =
        ViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.card_contact, parent, false)
        )

    override fun onBindViewHolder(holder: ViewHolder, position: Int) =
        holder.setData(items[position], contact_name)
}

编辑 2:早些时候我认为 SimpleDateFormat 是错误的。但它实际上是TimePicker。它以某种方式错误地解释了对 24 小时按钮的点击,而是将对应的 12 小时按钮注册为输入。

例如,如果我第一次选择18:30作为时间,那么如果我第二次选择6:30作为时间,则生成的时间仍然是18:30。但是如果第三次改成18:30,现在注册时间是6:30.

我创建了一个 DateTimePickerSample 来帮助你。最初的问题是错误地使用了 java.util.Calendar 中的 HOUR。使用 HOUR_OF_DAY returns 正确的结果。

来自Java Documenation

HOUR: Field number for get and set indicating the hour of the morning or afternoon. HOUR_OF_DAY: Field number for get and set indicating the hour of the day.

用法:

val picker = DateTimePickerSample(this)
picker.pickDateTime(
    usePreviousCalendar = true,
    callback = object: DateTimePickerSample.Callback {

        override fun onDateTimeSetSet(dateTimeStr: String, is24HourFormat: Boolean) {
            Log.d("Duh", "date=$dateTimeStr, is24HourFormat=$is24HourFormat")
        }
    }
)

DateTimePickerSample.kt

import android.app.DatePickerDialog
import android.app.TimePickerDialog
import android.content.Context
import android.text.format.DateFormat
import android.widget.DatePicker
import android.widget.TimePicker
import java.text.SimpleDateFormat
import java.util.*

class DateTimePickerSample(
    private val context: Context
) : DatePickerDialog.OnDateSetListener,
    TimePickerDialog.OnTimeSetListener {

    interface Callback {
        fun onDateTimeSetSet(dateTimeStr: String, is24HourFormat: Boolean)
    }

    private var callback: Callback? = null
    private var calendar = Calendar.getInstance()

    private val is24HourFormat = DateFormat.is24HourFormat(context)

    fun pickDateTime(usePreviousCalendar: Boolean, callback: Callback) {
        this.callback = callback
        if (!usePreviousCalendar) {
            this.calendar = Calendar.getInstance()
        }

        val datePickerDialog = createDatePicker()
        datePickerDialog.show()
    }

    private fun createDatePicker(): DatePickerDialog {
        return DatePickerDialog(
            context,
            this,
            calendar[Calendar.YEAR],
            calendar[Calendar.MONTH],
            calendar[Calendar.DAY_OF_MONTH]
        )
    }

    private fun createTimePicker(): TimePickerDialog {
        return TimePickerDialog(
            context,
            this,
            calendar[Calendar.HOUR_OF_DAY],
            calendar[Calendar.MINUTE],
            is24HourFormat
        )
    }

    /*
     * DatePickerDialog.OnDateSetListener
     */

    override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
        calendar[Calendar.YEAR] = year
        calendar[Calendar.MONTH] = month
        calendar[Calendar.DAY_OF_MONTH] = dayOfMonth

        val timePickerDialog = createTimePicker()
        timePickerDialog.show()
    }

    /*
     * TimePickerDialog.OnTimeSetListener
     */

    override fun onTimeSet(view: TimePicker?, hourOfDay: Int, minute: Int) {
        calendar[Calendar.HOUR_OF_DAY] = hourOfDay
        calendar[Calendar.MINUTE] = minute

        val dateFormatter = if (is24HourFormat) {
            SimpleDateFormat("dd mmm, yyyy 'at' HH:mm", Locale.getDefault())
        } else {
            SimpleDateFormat("dd mmm, yyyy 'at' hh:mm aa", Locale.getDefault())
        }

        val dateTimeStr = dateFormatter.format(calendar.time)
        callback?.onDateTimeSetSet(dateTimeStr, is24HourFormat)
    }
}