【问题标题】:How to use DatePickerDialog in Kotlin?如何在 Kotlin 中使用 DatePickerDialog?
【发布时间】:2017-08-23 14:11:32
【问题描述】:

在 Java 中可以使用 DatePickerDialog,例如:

final Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH);
int day = c.get(Calendar.DAY_OF_MONTH);


DatePickerDialog dpd = new DatePickerDialog(getActivity(),new DatePickerDialog.OnDateSetListener()
{
   @Override
   public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
  {
      // Display Selected date in textbox
      lblDate.setText(""+ dayOfMonth+" "+MONTHS[monthOfYear] + ", " + year);
  }
}, year, month,day);
dpd.show();

Kotlin 的 DatePickerDialog 使用如何?

【问题讨论】:

    标签: kotlin datepickerdialog


    【解决方案1】:

    看起来像这样:

    val c = Calendar.getInstance()
    val year = c.get(Calendar.YEAR)
    val month = c.get(Calendar.MONTH)
    val day = c.get(Calendar.DAY_OF_MONTH)
    
    
    val dpd = DatePickerDialog(activity, DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
    
        // Display Selected date in textbox
        lblDate.setText("" + dayOfMonth + " " + MONTHS[monthOfYear] + ", " + year)
    
    }, year, month, day)
    
    dpd.show()
    

    这是通过简单地将代码复制并粘贴到 android studio 中的 kotlin 文件中来完成的。我强烈推荐使用它。

    【讨论】:

    • 在这种情况下如何设置最大和最小日期?
    • @ASN 你会去dpd.datePicker.maxDate = 10和minDate一样
    • 谢谢你的帮助
    • 可以禁用未来日期dpd.datePicker.maxDate = System.currentTimeMillis()
    【解决方案2】:
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
    
            val textView: TextView  = findViewById(R.id.textView_date)
            textView.text = SimpleDateFormat("dd.MM.yyyy").format(System.currentTimeMillis())
    
            var cal = Calendar.getInstance()
    
            val dateSetListener = DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
                cal.set(Calendar.YEAR, year)
                cal.set(Calendar.MONTH, monthOfYear)
                cal.set(Calendar.DAY_OF_MONTH, dayOfMonth)
    
                val myFormat = "dd.MM.yyyy" // mention the format you need
                val sdf = SimpleDateFormat(myFormat, Locale.US)
                textView.text = sdf.format(cal.time)
    
            }
    
            textView.setOnClickListener {
                DatePickerDialog(this@MainActivity, dateSetListener,
                        cal.get(Calendar.YEAR),
                        cal.get(Calendar.MONTH),
                        cal.get(Calendar.DAY_OF_MONTH)).show()
            }
        }
    }
    

    【讨论】:

      【解决方案3】:

      Kotlin Anko Android 示例:

      alert {
      
          isCancelable = false
      
          lateinit var datePicker: DatePicker
      
          customView {
              verticalLayout {
                  datePicker = datePicker {
                      maxDate = System.currentTimeMillis()
                  }
              }
          }
      
          yesButton {
              val parsedDate = "${datePicker.dayOfMonth}/${datePicker.month + 1}/${datePicker.year}"
          }
      
          noButton { }
      
      }.show()
      

      【讨论】:

      • 我正在寻找类似的东西。谢谢兄弟!
      • 在 github here 的 Anko 项目上打开了一个问题。对话框是用错误的布局创建的
      【解决方案4】:

      在按钮点击时使用显示日期选择器

         val cal = Calendar.getInstance()
          val y = cal.get(Calendar.YEAR)
          val m = cal.get(Calendar.MONTH)
          val d = cal.get(Calendar.DAY_OF_MONTH)
      
      
          val datepickerdialog:DatePickerDialog = DatePickerDialog(activity, DatePickerDialog.OnDateSetListener { view, year, monthOfYear, dayOfMonth ->
      
          // Display Selected date in textbox
          lblDate.setText("" + dayOfMonth + " " + MONTHS[monthOfYear] + ", " + year)
              }, y, m, d)
      
          datepickerdialog.show()
      

      这用于在按钮单击时显示时间选择器

      textView54.setOnClickListener {
                      val c:Calendar= Calendar.getInstance()
                      val hh=c.get(Calendar.HOUR_OF_DAY)
                      val mm=c.get(Calendar.MINUTE)
                      val timePickerDialog:TimePickerDialog=TimePickerDialog(this@VendorRegistration,TimePickerDialog.OnTimeSetListener { view, hourOfDay, minute ->
                          textView54.setText( ""+hourOfDay + ":" + minute);
                      },hh,mm,true)
                      timePickerDialog.show()
      

      【讨论】:

      • 添加 TimePicker 对话框的好方法。
      【解决方案5】:

      如果您想使用协程来桥接回调模式,您可以使用这样的解决方案。请注意,我在这里同时使用了日期和时间选择器,但如果您不需要 TimePicker 逻辑,您可以轻松删除它。

      suspend fun Context.openDateTimePicker(calendar: Calendar = Calendar.getInstance()): Instant =
          suspendCoroutine { continuation ->
              val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, day ->
                  val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
                      calendar
                          .apply { set(year, month, day, hour, minute) }
                          .run { Instant.ofEpochMilli(timeInMillis).truncatedTo(ChronoUnit.MINUTES) }
                          .let { continuation.resume(it) }
                  }
      
                  TimePickerDialog(
                      this,
                      timeSetListener,
                      calendar.get(Calendar.HOUR_OF_DAY),
                      calendar.get(Calendar.MINUTE),
                      DateFormat.is24HourFormat(this)
                  ).show()
              }
      
              DatePickerDialog(
                  this,
                  dateSetListener,
                  calendar.get(Calendar.YEAR),
                  calendar.get(Calendar.MONTH),
                  calendar.get(Calendar.DAY_OF_MONTH)
              ).show()
          }
      

      【讨论】:

        【解决方案6】:

        我使用 Kotlin,所以我想要一个 Kotlin 解决方案,而不是 Java 解决方案。

        所以首先我会仔细研究@FrostRocket 的解决方案作为起点。 @FrostRocket 的解决方案对我很有用。

        就我而言,我忽略了所有的 Kotlin 世界。以及我只能使用 OffsetDateTime 而不能使用日历类。另外,我之前从来没有用过协程,所以我不得不阅读和研究 Kotlin 中的协程。如果您在我的代码中发现一些理论或实际错误,请告诉我。

        首先在我的扩展包中添加一个新文件:ContextExtention.kt

        import android.app.DatePickerDialog
        import android.app.TimePickerDialog
        import android.content.Context
        import android.text.format.DateFormat
        import java.time.OffsetDateTime
        import kotlin.coroutines.resume
        import kotlin.coroutines.suspendCoroutine
        
            suspend fun Context.openDateTimePicker(offsetDateTime: OffsetDateTime = OffsetDateTime.now()): OffsetDateTime =
        suspendCoroutine { continuation ->
            val dateSetListener = DatePickerDialog.OnDateSetListener { _, year, month, day ->
                //month (0-11 for compatibility with Calendar#MONTH)
                // day of the month (1-31, depending on month)
                val timeSetListener = TimePickerDialog.OnTimeSetListener { _, hour, minute ->
                    offsetDateTime.let {
                    val newOffsetDateTime =
                        offsetDateTime.withHour(hour).withMinute(minute).withYear(year)
                            //withMonth from 1 (January) to 12 (December)
                            //so I have to adapt it.
                            .withMonth((month+1))
                            //withDayOfMonth from 1 to 28-31
                            //so no need adaptation
                            .withDayOfMonth(day)
                            continuation.resume(newOffsetDateTime)
                        }
                }
        
                TimePickerDialog(
                    this,
                    timeSetListener,
                    offsetDateTime.hour,
                    offsetDateTime.minute,
                    DateFormat.is24HourFormat(this)
                ).show()
            }
        
            //the initially selected month (0-11 for compatibility with Calendar#MONTH)
            //when offsetDateTime.monthValue from 1 (January) to 12 (December)
            //so I have to adapt it.
            DatePickerDialog(
                this,
                dateSetListener,
                offsetDateTime.year,
                (offsetDateTime.monthValue-1),
                offsetDateTime.dayOfMonth
            ).show()
        }
        

        那么我怎样才能运行一个挂起的函数呢?所以你在 kotlinx.coroutines.Job 中运行一个协程,CoroutineScope 让我想起了 iPhone 编程中的 Grand Central Dispatcher 那里有一个服务质量列表。

        在这种情况下,如果您想使用 UI 线程,您必须使用:Dispatchers.Main 或 Dispatchers.Main.immediate 如果您需要更好的服务。

        import android.widget.TextView
        import androidx.lifecycle.Observer
        // the R import here 
        // the openDateTimePicker import here 
        // the TimeHelper (is text formatter) import here 
        import kotlinx.coroutines.CoroutineScope
        import kotlinx.coroutines.Dispatchers
        import kotlinx.coroutines.Job
        import kotlinx.coroutines.launch
        
        
        class FooFragment : Fragment() {
        
        private lateinit var viewModel: FooViewModel
        
        private lateinit var dateButton: Button
        private lateinit var dateText: TextView
        private var datePickerJob : Job? = null
        val uiScope = CoroutineScope(Dispatchers.Main)
        
        override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val root =
             inflater.inflate(R.layout.foo_fragment, container, false)
            dateButton = root.findViewById(R.id.textButtonChangeDate)
            dateText = root.findViewById(R.id.textViewWeighingDateValue)
            viewModel = ViewModelProvider(this).get(FooViewModel::class.java)
            return root
        }
        
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            viewModel.dateTimeText.observe(viewLifecycleOwner, Observer {
                dateText.text = it.format(TimeHelper.formatter)
        //the call to setNewDateTime will refresh this value
            })
        }
        
        override fun onStart() {
            super.onStart()
            dateButton.setOnClickListener {
                datePickerJob = uiScope.launch {
                    viewModel.setNewDateTime(context?.openDateTimePicker())
        //setNewDateTime is a setValue in a MutableLiveData
                }
            }
        
        }
        
        override fun onStop() {
            super.onStop()
            dateButton.setOnClickListener(null)
            datePickerJob?.cancel()
        }
        
        }
        

        【讨论】:

        • 不错的一个。但是,我不明白。
        • 首先我创建了一个名为 openDateTimePicker 的暂停协程,它接收一个 OffsetDateTime 或者它将使用默认值(“现在时间”)。 openDateTimePicker 将创建一个新的 DatePickerDialog 并调用 show。 DatePickerDialog 将调用 dateSetListener 来处理响应。 dateSetListener 将创建一个 TimePickerDialog 并调用 show。 TimePickerDialog 将调用 timeSetListener 来处理响应。 timeSetListener 将在 newOffsetDateTime 中收集所有信息,并通过调用 continuation.resume 将其发送给 openDateTimePicker 的调用者。快乐的黑客 nyxee!
        • 这绝对是最好的答案。会采纳的。
        【解决方案7】:
        dateColumn.setOnClickListener {
                val c = Calendar.getInstance()
                val yr = c.get(Calendar.YEAR)
                val month = c.get(Calendar.MONTH)
                val day = c.get(Calendar.DAY_OF_MONTH)
                val display = DatePickerDialog(context as BaseActivity, DatePickerDialog.OnDateSetListener {
                        view, year, monthOfYear, dayOfMonth ->
                    var monthInput = (monthOfYear + 1).toString()
                    if (monthInput.toInt() == 1) {
                        monthInput = "Jan"
                    } else if (monthInput.toInt() == 2) {
                        monthInput = "Feb"
                    } else if (monthInput.toInt() == 3) {
                        monthInput = "March"
                    } else if (monthInput.toInt() == 4) {
                        monthInput = "April"
                    } else if (monthInput.toInt() == 5) {
                        monthInput = "May"
                    } else if (monthInput.toInt() == 6) {
                        monthInput = "June"
                    } else if (monthInput.toInt() == 7) {
                        monthInput = "July"
                    } else if (monthInput.toInt() == 8) {
                        monthInput = "Aug"
                    } else if (monthInput.toInt() == 9) {
                        monthInput = "Sept"
                    } else if (monthInput.toInt() == 10) {
                        monthInput = "Oct"
                    } else if (monthInput.toInt() == 11) {
                        monthInput = "Nov"
                    } else if (monthInput.toInt() == 12) {
                        monthInput = "Dec"
                    }
                    dateColumn.text = ("$dayOfMonth $monthInput, $year")
                }, yr, month, day)
                display.datePicker.minDate = System.currentTimeMillis()
                display.show()
            }
        

        【讨论】:

        • 请不要只用代码回答问题。请说明您的代码如何工作以及如何解决问题。
        猜你喜欢
        • 2022-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-05-19
        相关资源
        最近更新 更多