Android/Kotlin 如何实现DialogFragment向Fragment传递数据
Android DialogFragment向父Fragment传值实现方案
针对你的需求,这里提供两种可直接落地的实现方式,均基于你现有代码修改:
方案1:接口回调实现(适合简单传值场景,逻辑直观)
步骤1:修改TimePickerFragment.kt,定义回调接口
package com.example.mytablayout.fragments import android.app.Dialog import android.app.TimePickerDialog import android.content.Context import android.os.Bundle import android.text.format.DateFormat import android.widget.TimePicker import androidx.fragment.app.DialogFragment import java.util.* class TimePickerFragment: DialogFragment(), TimePickerDialog.OnTimeSetListener { // 定义时间选择回调接口 interface OnTimeSelectedListener { fun onTimeSelected(hour: Int, minute: Int) } private lateinit var listener: OnTimeSelectedListener // Fragment绑定上下文时获取父Fragment的回调实例 override fun onAttach(context: Context) { super.onAttach(context) // 你是通过Weight的childFragmentManager启动弹窗,所以parentFragment就是Weight实例 listener = parentFragment as OnTimeSelectedListener } override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val c = Calendar.getInstance() val hour = c.get(Calendar.HOUR_OF_DAY) // 这里建议用HOUR_OF_DAY避免12小时制问题 val minute = c.get(Calendar.MINUTE) return TimePickerDialog(requireActivity(), this, hour, minute, DateFormat.is24HourFormat(activity)) } override fun onTimeSet(view: TimePicker, hour: Int, minute: Int) { // 选中时间后触发回调,把值传给父Fragment listener.onTimeSelected(hour, minute) } }
步骤2:修改Weight.kt,实现回调接口更新按钮
注意:你原代码中把btnTime声明为全局变量会有内存泄漏风险,建议移到类内部作为私有成员
package com.example.mytablayout import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Button import androidx.fragment.app.Fragment import com.example.mytablayout.fragments.TimePickerFragment import java.util.* class Weight : Fragment(), TimePickerFragment.OnTimeSelectedListener { // 把按钮声明移到类内部 private lateinit var btnTime: Button override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_weight, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val c = Calendar.getInstance() val hour = c.get(Calendar.HOUR_OF_DAY) val minute = c.get(Calendar.MINUTE) btnTime = view.findViewById(R.id.btnTime) btnTime.text = String.format("%02d:%02d", hour, minute) btnTime.setOnClickListener { val newTimeFragment = TimePickerFragment() newTimeFragment.show(childFragmentManager, "timePicker") } } // 实现回调接口,接收选中的时间更新按钮 override fun onTimeSelected(hour: Int, minute: Int) { btnTime.text = String.format("%02d:%02d", hour, minute) } }
方案2:ViewModel实现(适合复杂场景,配置变更不丢失数据)
如果你的项目后续有更复杂的数据共享需求,推荐用ViewModel实现,无需写回调接口。
步骤1:新建共享ViewModel类TimeViewModel.kt
package com.example.mytablayout import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel class TimeViewModel : ViewModel() { private val _selectedTime = MutableLiveData<String>() val selectedTime: LiveData<String> = _selectedTime fun updateTime(hour: Int, minute: Int) { _selectedTime.value = String.format("%02d:%02d", hour, minute) } }
步骤2:修改TimePickerFragment.kt,选中时间后更新ViewModel
override fun onTimeSet(view: TimePicker, hour: Int, minute: Int) { // 获取和父Fragment共享的ViewModel实例 val timeViewModel = ViewModelProvider(requireParentFragment())[TimeViewModel::class.java] timeViewModel.updateTime(hour, minute) }
步骤3:修改Weight.kt,观察ViewModel数据更新按钮
class Weight : Fragment() { private lateinit var btnTime: Button // 初始化当前Fragment作用域的ViewModel private val timeViewModel: TimeViewModel by viewModels() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // ...原有初始化代码不变 // 观察时间变化自动更新按钮 timeViewModel.selectedTime.observe(viewLifecycleOwner) { timeStr -> btnTime.text = timeStr } btnTime.setOnClickListener { val newTimeFragment = TimePickerFragment() newTimeFragment.show(childFragmentManager, "timePicker") } } }
内容的提问来源于stack exchange,提问作者MZX
相关产品推荐
相关产品推荐

