Reputation:
I have a toolbar in activity with a fragment container
<androidx.appcompat.widget.Toolbar
android:id="@+id/tlUsersActivity"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/white"
/>
I run these lines to control the backpressed button
setSupportActionBar(binding?.tlUsersActivity)
if (supportActionBar != null) {
when (intent.getStringExtra(MainActivityAdmin.FRAGMENT_TYPE)) {
"View Users" -> {
supportActionBar?.title = viewUsersText
}
"Edit Users" -> {
supportActionBar?.title = editUsersText
}
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding?.tlUsersActivity?.setNavigationOnClickListener { onBackPressed() }
I want to change this action from inside the fragment, I want to replace it with a function that replaces fragments. I've tried this but it didn't work
val actionBar = view?.findViewById<Toolbar>(R.id.tlUsersActivity)
actionBar?.setNavigationOnClickListener {
replaceFragment(FragmentEditUsers())
}
Upvotes: 0
Views: 968
Reputation: 3265
Directly working with Activity from the fragment is not a good practice, it will become a nest of bugs in the future))
The first option is SharedViewModel
which you can share between your activity and fragment. But maybe you don't want it if you have simple functionality and you don't want to involve ViewModel
here.
The second option, which usually was used before Fragment Result API
and SharedViewModel
were callbacks.
The third one which I prefer and it's way cleaner is Fragment Result API
.
You can find more information here - FragmentResultAPI & SharedViewModel.
Using it you can communicate between activity-to-fragment, vice-versa, and fragment-to-fragment.
You need a Gradle dependency to use it:
implementation "androidx.fragment:fragment-ktx:1.4.1"
In the activity, you have to set a FragmentResultListener
. It takes as a parameter the request key, lifecycle, and FragmentResultListener
interface which is a SAM interface (has only 1 function). You can deep-dive here if you want.
const val REQUEST_KEY = "101"
const val BUNDLE_KEY = "B101"
// Activity code
supportFragmentManager.setFragmentResultListener(REQUEST_KEY, this) { requestKey, bundle ->
if (requestKey == REQUEST_KEY) {
// Here you can call the functions you desire
Toast.makeText(this, bundle.getString(BUNDLE_KEY), Toast.LENGTH_SHORT).show()
}
}
Now let's have a look at the fragment side. I have one button and after clicking I trigger the result listener in the activity:
// Fragment code
val btnTriggerActivity = view.findViewById<Button>(R.id.btn_trigger_activity)
btnTriggerActivity.setOnClickListener {
// This code will trigger the function in activity.
// The activity will show the toast
setFragmentResult(REQUEST_KEY, bundleOf(
BUNDLE_KEY to "Hello from the other side :)"
))
}
That's it. Here's also an image from the developer's page which shows the communication of fragment-to-fragment using FragmentResultApi
.
Upvotes: 1