Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/198.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 使用导航控制器时,从DatePickerDialog片段返回日期时出现问题_Android_Kotlin_Android Datepicker_Android Architecture Navigation - Fatal编程技术网

Android 使用导航控制器时,从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

我正在尝试返回从DatePickerDialog中选择的日期。我知道这里有一些关于这个的问题,我确信我已经在代码中检查了这些问题,我仍然无法将日期返回到调用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{{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分吗?没问题,兄弟,你有更重要的解决办法。