从底部弹出的对话框片段中获取值

20

我从A fragment启动了bottomSheetDialogFragment。

我想从该bottomSheetDialogFragment中选择日期,然后将其设置在fragment A中。

日期已经选择好了,我只是想要在fragment A中获取它并设置在一些字段中。

如何获取该值呢? 有什么建议吗?


分享你的代码 - Anonymous
6
创建一个接口,然后在A片段中实现该接口,并将该接口的引用传递到BottomSheetDialog中。当您更改日期时,在该方法中调用该接口方法并将您的日期传递给方法参数。现在您已经在Fragment A中拥有了您的日期,请使用它。 - Däñish Shärmà
你能写一个例子吗? - Abdulrahman
8个回答

24

创建一个像这样的接口类

public interface CustomInterface {

    public void callbackMethod(String date);
}

在您的ActivityFragment中实现此接口,并创建该接口的对象。

private CustomInterface callback;

onCreateonCreateView中初始化它。

callback=this;

现在,当您调用BottomSheetDialogFragment时,请将此回调函数传递给构造函数。

yourBottomSheetObject = new YourBottomSheet(callback);
yourBottomSheetObject.show(getSupportFragmentManager()," string");

现在在你的BottomSheetFragment的构造函数中:

private CustomInterface callback;

public SelectStartTimeSheet(CustomInterface callback){

this.callback=callback;

}

最后,使用这个回调对象来设置您的日期。

callback.callbackMethod("your date");

你将在callbackMethod函数中收到这个数据,可以在Fragment或Activity中接收。


3
这对我没有效果。当我在BottomSheetFragment中创建一个带参数的构造函数时,它会抛出警告,提示“避免在片段中使用非默认构造函数”...有什么解决方法吗?谢谢。 - jackycflau
只需要在你的类名上添加这行代码 @SuppressLint("ValidFragment")。 - AbhayBohra
5
不要抑制,可以这样做:fragment.setCallbackListener(listener)。 但是,如果你是从一个fragment或activity中调用,这仍然不是首选方法。例如,在fragment的情况下,可以使用getTargetFragment()。 - Andrea Aranguren
@AndreaAranguren提供了更好的解决方案,使用getTargetFragment。这应该是被选择的答案。 - Avi

10

覆盖片段的构造函数是一种不良实践,因为文档中说:

每个片段都必须有一个空构造函数,这样当恢复其活动状态时可以实例化它。

如果您使用传递回调作为参数的另一个构造函数,则当框架恢复片段时,您的应用程序将崩溃。

推荐的方法是使用viewModel和livedata。


9

Android导航架构组件

例如:

假设您使用navController从Fragment A打开Fragment B。

并且您想要从Fragment B向Fragment 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()

        }
}

并且在您的 Fragment A 中:

findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("your_key")
                ?.observe(viewLifecycleOwner) {
    
                    if (it == "your_value") {
                        //your code
    
                    }
    
                }

3
您可以按照以下步骤进行操作:

选择账号片段代码


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()
    }

}



现在,按照以下步骤在另一个片段/活动中显示并获取回调:
 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());

2
如果您正在使用BottomSheetDialogFragment,由于它是一个片段,您应该在片段的onAttach生命周期方法中创建您的接口并绑定到它,将活动引用适当转换为您的侦听器/回调类型。
在您的活动中实现此接口,并在某人点击片段内部recyclerview中的项目时进行更改分派,例如。
这是一种众所周知的模式,在这里有更好的解释。
一个重要的建议是重新考虑您的应用程序架构,因为最好的方法始终是通过Bundle在Android组件之间传递原始/简单/微小的数据,您的组件能够稍后使用其依赖项检索所需的状态。
例如,您永远不应传递像位图、数据类、DTO或视图引用之类的大型对象。
首先,存在一些关于Parcel的序列化过程会影响应用程序的响应性;第二,它可能会导致TransactionTooLarge类型的错误。
希望这可以帮助您!

0

您可以使用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)
        }
    })
}

欲知详情,请阅读文档


0

你也可以使用LocalBroadcastManager。正如hglf所说,最好保留片段的空构造函数,并使用newInstance(Type value)来实例化片段,如果你仍然想使用接口回调方式。


-5

被接受的答案是错误的。

你可以做的就是在调用show()时使用Fragment A的childFragmentManager。

像这样:

val childFragmentManager = fragmentA.childFragmentManager
bottomSheetDialogFragment.show(childFragmentManager, "dialog") 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接