Android 使用导航控制器时,从DatePickerDialog片段返回日期时出现问题
我正在尝试返回从DatePickerDialog中选择的日期。我知道这里有一些关于这个的问题,我确信我已经在代码中检查了这些问题,我仍然无法将日期返回到调用DatePickerDialog的片段中 我正在使用导航组件显示对话框,这可能是导致问题的原因吗 这是我的DatePickerDialog:Android 使用导航控制器时,从DatePickerDialog片段返回日期时出现问题,android,kotlin,android-datepicker,android-architecture-navigation,Android,Kotlin,Android Datepicker,Android Architecture Navigation,我正在尝试返回从DatePickerDialog中选择的日期。我知道这里有一些关于这个的问题,我确信我已经在代码中检查了这些问题,我仍然无法将日期返回到调用DatePickerDialog的片段中 我正在使用导航组件显示对话框,这可能是导致问题的原因吗 这是我的DatePickerDialog: class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener { private var on
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{{uuz,hasFocus->showDatePicker(hasFocus,fragmentView)}
问题:如何将日期返回到调用DatePickerDialog的片段中。我不希望DatePickerDialog作为调用它的类的内部类 可以设置目标
片段:
val fragment = DatePickerFragment()
fragment.setTargetFragment(this, requestCode)
/* 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.");
}
@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 */
}
}
}
...
}
}
或者让它将结果传递给活动
:
val fragment = DatePickerFragment()
fragment.setListeningActivity(this)
if(this.dialog.getOwnerActivity() != null) {
...
}
这应该在显示对话框片段之前发生;这样,对话框片段
就已经知道将结果传递到哪里。对于任一交付目的地,方法onDateSet()
需要返回一个带有附加包的Intent
。。。并且需要处理该结果并相应地更新GUI。这就是活动
和片段
之间的通信方式-这也适用于对话框片段
。方法onActivityResult()
可以处理来自Activity
和Fragment
的回调
在Java中,这与此类似-用于在对话框片段中返回结果,在方法中覆盖日期集(视图:日期选择器,年:Int,月:Int,日:Int)
:
或类似地返回到活动
:
val fragment = DatePickerFragment()
fragment.setListeningActivity(this)
if(this.dialog.getOwnerActivity() != null) {
...
}
以及打开对话框Fragment
的活动或片段的onActivityResult()
:
val fragment = DatePickerFragment()
fragment.setTargetFragment(this, requestCode)
/* 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.");
}
@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 */
}
}
}
...
}
}
返回片段
结果与返回活动
结果几乎相同。传递片段数据的最佳方法是使用导航架构组件时,使用viewmodel
使用livedata
第1步创建视图模型
,该模型将保存您的所选日期
。创建LiveData
的实例,以便观察更改
class SharedViewModel: ViewModel() {
val selectedDate: MutableLiveData<String> = MutableLiveData()
}
步骤3获取SharedViewModel
的实例,您希望在其中观察更改。(在我们的例子中,从这里调用datePickerFragment
)
如果您使用的是androidx
工件。那么您可能需要以下依赖项
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-alpha01'
我建议将livedata
与ViewModel
一起使用。最简单的解决方案是使用Hey-man,很抱歉没有早点回到这里。这非常有效,感谢详细的解释和示例代码。只是一个简单的问题,为什么标准的监听器在使用导航控制器时不能工作?我不确定。但我想,它没有';无法工作,因为片段的实例是由navcontroller创建的。所以在这种情况下,我们不';在原始片段中没有正确的引用。是的,很抱歉。有什么办法我可以给你50分吗?没问题,兄弟,你有更重要的解决办法。