从底部 Sheet 对话框片段获取值
Get value from Bottom Sheet Dialog Fragment
我从片段 A 开始 bottomSheetDialogFragment。
我想 select 来自 bottomSheetDialogFragment 的日期,然后将其设置在片段 A 中。
select日期已经做好了,我只是想在片段A中获取它,以便在某些字段中设置它。
如何获取值?
有什么建议吗?
像这样创建一个界面class
public interface CustomInterface {
public void callbackMethod(String date);
}
在您的 Activity
或 Fragment
中实现此接口。并创建此接口的对象。
private CustomInterface callback;
在onCreate
或onCreateView
中初始化
callback=this;
现在调用它时在 BottomSheetDialogFragment
构造函数中传递此回调。
yourBottomSheetObject = new YourBottomSheet(callback);
yourBottomSheetObject.show(getSupportFragmentManager()," string");
现在在 BottomSheetFragment 的构造函数中
私有自定义接口回调;
public SelectStartTimeSheet(CustomInterface callback){
this.callback=callback;
}
最后使用这个回调对象来设置你的日期
callback.callbackMethod("your date");
并且您将在您的片段或 callbackMethod
函数中的 Activity 中收到此日期。
如文档所述,重写片段的构造函数是一种不好的做法:
Every fragment must have an
* empty constructor, so it can be instantiated when restoring its
* activity's state.
如果您使用另一个将回调作为参数传递的构造函数,当框架恢复片段时,您的应用程序会崩溃
推荐的方式是使用 viewModel 和 livedata。
您也可以使用LocalBroadcastManager。正如 hglf 所说,如果您仍想使用接口回调方式,最好为您的片段保留空构造函数并使用 newInstance(Type value) 来实例化您的片段。
您可以按如下方式使用:
Select 帐户片段代码
class SelectAccountFragment(val clickListener: OnOptionCLickListener) : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.bottom_fragment_accounts, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val list = DataProcessorApp(context).allUsers
val rvAccounts = view.findViewById<RecyclerView>(R.id.rvAccounts)
rvAccounts.layoutManager = LinearLayoutManager(context)
rvAccounts.adapter = AccountsAdapter(context, list)
Log.e(tag,"Accounts "+list.size);
tvAccountAdd.setOnClickListener {
val intent = Intent(context,LoginActivity::class.java)
startActivity(intent)
}
tvManageAccounts.setOnClickListener {
Log.e(tag,"Manage Click")
clickListener.onManageClick()
}
}
interface OnOptionCLickListener{
fun onManageClick()
}
}
现在显示并调用回另一个片段 /activity 如下
SelectAccountFragment accountFragment = new SelectAccountFragment(() -> {
//get fragment by tag and dismiss it
BottomSheetDialogFragment fragment = (BottomSheetDialogFragment) getChildFragmentManager().findFragmentByTag(SelectAccountFragment.class.getSimpleName();
if (fragment!=null){
fragment.dismiss();
}
});
accountFragment.show(getChildFragmentManager(),SelectAccountFragment.class.getSimpleName());
如果您正在使用 BottomSheetDialogFragment ,因为它是一个片段,您应该创建您的界面并在片段的 onAttach 生命周期方法绑定到它,对 activity 引用进行适当的转换 listener/callback类型。
在您的 activity 中实现此接口,并在有人点击片段的内部回收视图的项目时发送更改,例如
这是一个众所周知的模式,在 here
中有更好的解释
一个重要的建议是重新考虑您的应用程序架构,因为最好的方法是始终通过 Bundle 在 Android 组件之间传递 primitive/simple/tiny 数据,并且您的组件能够通过它们检索所需的状态稍后依赖。
例如,您永远不应传递大型对象,例如位图、数据 类、DTO 或视图引用。
- 首先,有一些关于 Parcel 的序列化过程正在进行,这会影响应用程序的响应能力
- 其次,它可能会导致您出现 TransactionTooLarge 类型的错误。
希望对您有所帮助!
接受的答案是错误的。
调用show()时,用户Fragment A的childFragmentManager即可。
像这样:
val childFragmentManager = fragmentA.childFragmentManager
bottomSheetDialogFragment.show(childFragmentManager, "dialog")
您可以利用 Navigation
库的优势:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navController = findNavController();
// After a configuration change or process death, the currentBackStackEntry
// points to the dialog destination, so you must use getBackStackEntry()
// with the specific ID of your destination to ensure we always
// get the right NavBackStackEntry
val navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment)
// Create our observer and add it to the NavBackStackEntry's lifecycle
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME
&& navBackStackEntry.savedStateHandle.contains("key")) {
val result = navBackStackEntry.savedStateHandle.get<String>("key");
// Do something with the result
}
}
navBackStackEntry.lifecycle.addObserver(observer)
// As addObserver() does not automatically remove the observer, we
// call removeObserver() manually when the view lifecycle is destroyed
viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_DESTROY) {
navBackStackEntry.lifecycle.removeObserver(observer)
}
})
}
有关详细信息,请阅读 the document。
Android 导航架构组件
例如:
假设您使用 navController 从 Fragment A 打开 Fragment B。
并且您需要从片段 B 到片段 A 的一些数据。
class B :BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.your_layout, container, false)
root.sampleButton.setOnClickListener {
val navController = findNavController()
navController.previousBackStackEntry?.savedStateHandle?.set("your_key", "your_value")
dismiss()
}
}
在您的片段 A 中:
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("your_key")
?.observe(viewLifecycleOwner) {
if (it == "your_value") {
//your code
}
}
我从片段 A 开始 bottomSheetDialogFragment。 我想 select 来自 bottomSheetDialogFragment 的日期,然后将其设置在片段 A 中。
select日期已经做好了,我只是想在片段A中获取它,以便在某些字段中设置它。
如何获取值? 有什么建议吗?
像这样创建一个界面class
public interface CustomInterface {
public void callbackMethod(String date);
}
在您的 Activity
或 Fragment
中实现此接口。并创建此接口的对象。
private CustomInterface callback;
在onCreate
或onCreateView
callback=this;
现在调用它时在 BottomSheetDialogFragment
构造函数中传递此回调。
yourBottomSheetObject = new YourBottomSheet(callback);
yourBottomSheetObject.show(getSupportFragmentManager()," string");
现在在 BottomSheetFragment 的构造函数中
私有自定义接口回调;
public SelectStartTimeSheet(CustomInterface callback){
this.callback=callback;
}
最后使用这个回调对象来设置你的日期
callback.callbackMethod("your date");
并且您将在您的片段或 callbackMethod
函数中的 Activity 中收到此日期。
如文档所述,重写片段的构造函数是一种不好的做法:
Every fragment must have an * empty constructor, so it can be instantiated when restoring its * activity's state.
如果您使用另一个将回调作为参数传递的构造函数,当框架恢复片段时,您的应用程序会崩溃
推荐的方式是使用 viewModel 和 livedata。
您也可以使用LocalBroadcastManager。正如 hglf 所说,如果您仍想使用接口回调方式,最好为您的片段保留空构造函数并使用 newInstance(Type value) 来实例化您的片段。
您可以按如下方式使用:
Select 帐户片段代码
class SelectAccountFragment(val clickListener: OnOptionCLickListener) : BottomSheetDialogFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.bottom_fragment_accounts, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val list = DataProcessorApp(context).allUsers
val rvAccounts = view.findViewById<RecyclerView>(R.id.rvAccounts)
rvAccounts.layoutManager = LinearLayoutManager(context)
rvAccounts.adapter = AccountsAdapter(context, list)
Log.e(tag,"Accounts "+list.size);
tvAccountAdd.setOnClickListener {
val intent = Intent(context,LoginActivity::class.java)
startActivity(intent)
}
tvManageAccounts.setOnClickListener {
Log.e(tag,"Manage Click")
clickListener.onManageClick()
}
}
interface OnOptionCLickListener{
fun onManageClick()
}
}
现在显示并调用回另一个片段 /activity 如下
SelectAccountFragment accountFragment = new SelectAccountFragment(() -> {
//get fragment by tag and dismiss it
BottomSheetDialogFragment fragment = (BottomSheetDialogFragment) getChildFragmentManager().findFragmentByTag(SelectAccountFragment.class.getSimpleName();
if (fragment!=null){
fragment.dismiss();
}
});
accountFragment.show(getChildFragmentManager(),SelectAccountFragment.class.getSimpleName());
如果您正在使用 BottomSheetDialogFragment ,因为它是一个片段,您应该创建您的界面并在片段的 onAttach 生命周期方法绑定到它,对 activity 引用进行适当的转换 listener/callback类型。
在您的 activity 中实现此接口,并在有人点击片段的内部回收视图的项目时发送更改,例如
这是一个众所周知的模式,在 here
中有更好的解释一个重要的建议是重新考虑您的应用程序架构,因为最好的方法是始终通过 Bundle 在 Android 组件之间传递 primitive/simple/tiny 数据,并且您的组件能够通过它们检索所需的状态稍后依赖。
例如,您永远不应传递大型对象,例如位图、数据 类、DTO 或视图引用。
- 首先,有一些关于 Parcel 的序列化过程正在进行,这会影响应用程序的响应能力
- 其次,它可能会导致您出现 TransactionTooLarge 类型的错误。
希望对您有所帮助!
接受的答案是错误的。
调用show()时,用户Fragment A的childFragmentManager即可。
像这样:
val childFragmentManager = fragmentA.childFragmentManager
bottomSheetDialogFragment.show(childFragmentManager, "dialog")
您可以利用 Navigation
库的优势:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val navController = findNavController();
// After a configuration change or process death, the currentBackStackEntry
// points to the dialog destination, so you must use getBackStackEntry()
// with the specific ID of your destination to ensure we always
// get the right NavBackStackEntry
val navBackStackEntry = navController.getBackStackEntry(R.id.your_fragment)
// Create our observer and add it to the NavBackStackEntry's lifecycle
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME
&& navBackStackEntry.savedStateHandle.contains("key")) {
val result = navBackStackEntry.savedStateHandle.get<String>("key");
// Do something with the result
}
}
navBackStackEntry.lifecycle.addObserver(observer)
// As addObserver() does not automatically remove the observer, we
// call removeObserver() manually when the view lifecycle is destroyed
viewLifecycleOwner.lifecycle.addObserver(LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_DESTROY) {
navBackStackEntry.lifecycle.removeObserver(observer)
}
})
}
有关详细信息,请阅读 the document。
Android 导航架构组件
例如:
假设您使用 navController 从 Fragment A 打开 Fragment B。
并且您需要从片段 B 到片段 A 的一些数据。
class B :BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val root = inflater.inflate(R.layout.your_layout, container, false)
root.sampleButton.setOnClickListener {
val navController = findNavController()
navController.previousBackStackEntry?.savedStateHandle?.set("your_key", "your_value")
dismiss()
}
}
在您的片段 A 中:
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("your_key")
?.observe(viewLifecycleOwner) {
if (it == "your_value") {
//your code
}
}