我试图返回从DatePickerDialog中选择的日期。我知道在SO上对此有一些疑问,我确定已经检查了代码中的内容,但仍无法将日期重新输入到调用DatePickerDialog的片段中。
我正在使用“导航”界面显示对话框,这可能是导致问题的原因吗?
这是我的DatePickerDialog:
class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener {
private var onDateSetListener: DatePickerDialog.OnDateSetListener? = null
fun setListeningActivity(listener: DatePickerDialog.OnDateSetListener) {
onDateSetListener = listener
}
override fun onDateSet(view: DatePicker?, year: Int, month: Int, dayOfMonth: Int) {
onDateSetListener?.onDateSet(view,year, month, dayOfMonth)
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
// Use the current date as the default date in the picker
val c = Calendar.getInstance()
val year = c.get(Calendar.YEAR)
val month = c.get(Calendar.MONTH)
val day = c.get(Calendar.DAY_OF_MONTH)
// Create a new instance of DatePickerDialog and return it
return DatePickerDialog(context, this, year, month, day)
}
}
片段中调用Datepicker的相关代码:
private fun showDatePicker(hasFocus: Boolean, view: View) {
Log.i(FRAGMENT_NAME, "Has focus $hasFocus")
val fragment = DatePickerFragment()
fragment.setListeningActivity(this)
if (hasFocus) {
Navigation.findNavController(view).navigate(R.id.datePickerFragment)
}
}
override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) {
Log.i(FRAGMENT_NAME, "Date received: $year-$month-$day")
fragmentView.dateOfBirthField.editText?.setText("$year-$month-$day")
}
这就是我调用showDatePicker方法的方式:
fragmentView.dateOfBirthField.editText?.setOnFocusChangeListener {_,hasFocus-> showDatePicker(hasFocus,fragmentView)}
问题:如何将日期重新放回调用DatePickerDialog的Fragment中。我不想将DatePickerDialog作为调用它的类的内部类。
答案 0 :(得分:1)
当您使用导航体系结构组件时,最好的片段数据传递方法是将livedata
与viewmodel
一起使用。
步骤1 创建ViewModel
,它将保存您的selectedDate
。创建LiveData
的实例,以便您可以观察到更改。
class SharedViewModel: ViewModel() {
val selectedDate: MutableLiveData<String> = MutableLiveData()
}
步骤2 获取SharedViewModel
的实例并更新selectedDate
变量以通知其观察者。 (在DatePickerFragment
中)
override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) {
val viewModel = ViewModelProviders.of(activity!!)[SharedViewModel::class.java]
viewModel.selectedDate.value = "$year $month $day"
}
步骤3 获取要观察更改的SharedViewModel
实例。 (在我们的情况下,是从datePickerFragment
处调用的。)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
ViewModelProviders.of(activity!!)[SharedViewModel::class.java]
.selectedDate
.observe(activity!!, Observer { dateOfBirthField.editText.setText(it) })
}
如果您正在使用androidx
工件。然后您可能需要依赖。
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha01'
答案 1 :(得分:0)
一个人都可以设置目标Fragment
:
val fragment = DatePickerFragment()
fragment.setTargetFragment(this, requestCode)
或让其将结果传递到Activity
:
val fragment = DatePickerFragment()
fragment.setListeningActivity(this)
这应该在显示DialogFragment
之前发生;这样DialogFragment
就已经知道将结果传送到哪里了。对于任何一个传递目的地,方法onDateSet()
需要返回带有附加Intent
...的Bundle
,而onActivityResult()需要处理该结果并相应地更新GUI。 Activity
和Fragment
之间的通信就是这样进行的-这也适用于DialogFragment
。方法onActivityResult()
可以处理来自Activity
和Fragment
的回调。
在Java中,这类似于-在方法DialogFragment
中通过override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int)
返回结果:
/* converting the selection to long integer */
GregorianCalendar date = new java.util.GregorianCalendar();
date.set(GregorianCalendar.YEAR, year);
date.set(GregorianCalendar.MONTH, month);
date.set(GregorianCalendar.DAY_OF_MONTH, day);
Log.d(LOG_TAG, "confirmed " + date.getTime());
long dueDate = date.getTime().getTime();
if (getTargetFragment() != null) {
/* stuffing the result value into a Bundle */
Intent intent = this.getActivity().getIntent();
Bundle extras = new Bundle();
extras.putLong(ArgumentKeys.ARGUMENT_SELECT_DUE_DATE, dueDate);
intent.putExtras(extras);
/* this delivers the result */
getTargetFragment().onActivityResult(getTargetRequestCode(), Activity.RESULT_OK, intent);
/* close dialog */
this.dismiss();
} else {
Log.w(LOG_TAG, ".setTargetFragment() had not been called.");
}
或类似地返回到Activity
:
if(this.dialog.getOwnerActivity() != null) {
...
}
以及onActivityResult()
或Activity
中打开Fragment
的{{1}}:
DialogFragment
返回@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
Bundle extras = intent.getExtras();
if(resultCode == Activity.RESULT_OK) {
switch (requestCode) {
case RequestCodes.REQUESTCODE_TASK_DUE_DATE: {
if(extras != null) {
long dueDate = extras.getLong(ArgumentKeys.ARGUMENT_SELECT_DUE_DATE, -1);
/* set the value in here */
}
}
}
...
}
}
结果的工作原理几乎类似于返回Fragment
结果。