I'm starting bottomSheetDialogFragment from a fragment A. I want to select the date from that bottomSheetDialogFragment then set it in the fragment A.
The select date is already done, I just want to get it in the fragment A to set it in some fields.
How can I get the value? Any suggestions how to do it?
Create an interface class like this
public interface CustomInterface {
public void callbackMethod(String date);
}
Implement this interface in your Activity
or Fragment
. and make an object of this Interface.
private CustomInterface callback;
Initialize it in onCreate
or onCreateView
callback=this;
Now pass this callback in your BottomSheetDialogFragment
constructor when you call it.
yourBottomSheetObject = new YourBottomSheet(callback);
yourBottomSheetObject.show(getSupportFragmentManager()," string");
Now in your BottomSheetFragment's constructor
private CustomInterface callback;
public SelectStartTimeSheet(CustomInterface callback){
this.callback=callback;
}
And at last use this callback object to set your date
callback.callbackMethod("your date");
and yout will recieve this date in your Fragment or Your Activity in callbackMethod
function.
override the constructor of a fragment is a bad practice as the document said:
Every fragment must have an * empty constructor, so it can be instantiated when restoring its * activity's state.
if you using another constructor that passing a callback as the param, when the fragment is resotored by the framework, your app crash
the recommend way is using viewModel and livedata.
Android navigation architecture component
eg:
Suppose you open Fragment B from Fragment A using navController.
and you want some data from fragment B to 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()
}
}
and in your Fragment A:
findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("your_key")
?.observe(viewLifecycleOwner) {
if (it == "your_value") {
//your code
}
}
you can use do as below:
Select Account Fragment code
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()
}
}
Now show and get call back into another fragment /activity as below
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());
If you are using BottomSheetDialogFragment , since it's a fragment, you should create your interface and bind to it at onAttach lifecycle method of the fragment , doing the appropriate cast of activity reference to your listener/callback type.
Implement this interface in your activity and dispatch change when someone click in a item of fragment's inner recyclerview, for instance
It's a well known pattern and are explained better at here
One big advice is rethink your app architecture, since the best approach is to always pass primitive/simple/tiny data between Android components through Bundle, and your components are able to retrieve the required state with their dependencies later on.
For example, you should never pass along large Objects like Bitmaps, Data Classes , DTO's or View References.
Hope that helps!
You can also use LocalBroadcastManager . And as hglf said, it is better to keep the empty constructor for your fragment and use newInstance(Type value) instead to instantiate your fragment if you still want to use the interface callBack way.
You can use the benefit of Navigation
library:
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)
}
})
}
For more info, read the document .
The accepted answer is wrong.
What you can do is just user Fragment A's childFragmentManager when calling show().
like this:
val childFragmentManager = fragmentA.childFragmentManager
bottomSheetDialogFragment.show(childFragmentManager, "dialog")
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.