如何在 Kotlin 中使用 DatePickerDialog?
How to use DatePickerDialog in Kotlin?
在 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 使用起来怎么样?
看起来像这样:
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 文件中完成的。我强烈推荐使用它。
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()
}
}
}
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()
在点击按钮时使用显示日期选择器
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 逻辑。
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()
}
我使用 Kotlin,所以我想要 Kotlin 解决方案而不是 Java 解决方案。
所以首先我仔细查看了@FrostRocket 的解决方案作为起点。 @FrostRocket 的解决方案对我很有用。
就我而言,我忽略了所有 Kotlin 世界。以及我只能使用 OffsetDateTime 而不能使用日历 class。另外,我之前从来没有用过coroutine,所以不得不去阅读和研究Kotlin中的coroutines。如果您在我的代码中发现一些理论或实践错误,请告诉我。
首先在我的扩展包中添加一个新文件: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。如果您需要更好的服务,请立即使用。
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()
}
}
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()
}
在 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 使用起来怎么样?
看起来像这样:
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 文件中完成的。我强烈推荐使用它。
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()
}
}
}
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()
在点击按钮时使用显示日期选择器
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 逻辑。
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()
}
我使用 Kotlin,所以我想要 Kotlin 解决方案而不是 Java 解决方案。
所以首先我仔细查看了@FrostRocket 的解决方案作为起点。 @FrostRocket 的解决方案对我很有用。
就我而言,我忽略了所有 Kotlin 世界。以及我只能使用 OffsetDateTime 而不能使用日历 class。另外,我之前从来没有用过coroutine,所以不得不去阅读和研究Kotlin中的coroutines。如果您在我的代码中发现一些理论或实践错误,请告诉我。
首先在我的扩展包中添加一个新文件: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。如果您需要更好的服务,请立即使用。
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()
}
}
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()
}