Reputation: 807
setTargetFragment()
is deprecated in Java, and I don't understand the correct replacement for it as android documentation uses it and is outdated. I believe the FragmentManager
is the correct replacement for it. I am using the deprecated setTargetFragment
function in my settings Preferences to create multiple preference screens. To do so, I originally followed the guide here which confusingly uses setTargetFragment
in the example. Below is my code:
build.gradle (Module: app)
...
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.preference:preference:1.1.1'
...
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var settingsButton: ImageButton
override fun onCreate(savedInstanceState: Bundle?) {
...
settingsButton = findViewById(R.id.settingsButtonMain)
settingsButton.setOnClickListener {
settingsClicked()
}
...
}
private fun settingsClicked() {
val settingsIntent = Intent(this, SettingsActivity::class.java)
startActivity(settingsIntent)
}
}
SettingsActivity.kt
class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
override fun onCreate(savedInstanceState: Bundle?) {
...
supportFragmentManager.beginTransaction().replace(R.id.settings, SettingsFragment(this)).commit()
supportFragmentManager.addOnBackStackChangedListener {
if(supportFragmentManager.backStackEntryCount == 0) {
title = "App Settings"
}
}
supportActionBar?.setDisplayHomeAsUpEnabled(true)
...
}
class SettingsFragment(cont: Context) : PreferenceFragmentCompat() {
private var context1: Context = cont
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
}
}
class Screen2PreferencesFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.screen2_preferences, null)
}
}
override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat?, pref: Preference): Boolean {
val args: Bundle = pref.extras
val fragment: Fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment)
fragment.arguments = args
fragment.setTargetFragment(caller, 0) //TROUBLE AREA. WHAT IS THE CORRECT REPLACEMENT HERE?
supportFragmentManager.beginTransaction().replace(R.id.settings, fragment).addToBackStack(null).commit()
return true
}
override fun onSupportNavigateUp(): Boolean {
if(supportFragmentManager.popBackStackImmediate()) {
return true
}
return super.onSupportNavigateUp()
}
}
Upvotes: 16
Views: 15456
Reputation: 29
JANUARY 2024
I replaced setTargetFragment
with setFragmentResultListener
in two DialogFragments (parent and child) and code below is based on that. I think for the ordinary fragments it works the same way.
Gradle:
implementation 'androidx.fragment:fragment-ktx:1.6.2'
onCreateDialog in parent DialogFragment:
Set FragmentResultListener for parentFragmentManager. Remember to launch child fragment using the same fragment manager!
...
parentFragmentManager.setFragmentResultListener("requestKey", this) { key, bundle ->
val result = bundle.getString("myKey")
//result is a string passed by child fragment
}
binding.someButton.setOnClickListener {
val dialog = ChildDialogFragment()
dialog.show(parentFragmentManager, "someTag")
}
...
Child DialogFragment:
I will pass String value to parent fragment on button click.
binding.someOtherButton.setOnClickListener {
val stringToPass = "blablabla"
val bundle = Bundle().apply {
putString("myKey", result)
}
parentFragmentManager.setFragmentResult("requestKey", bundle)
}
Enjoy!
Upvotes: 0
Reputation: 1
For the unresolved issue when trying to use setFragmentResult referring to the answer above, you could try using the fragmentManager as follows.
This is for Xamarin:
ParentFragmentManager.SetFragmentResult("requestKey", bundle);
Upvotes: 0
Reputation: 20714
Include this dependency:
implementation 'androidx.fragment:fragment-ktx:1.3.0-beta01'
Use setFragmentResultListener
instead of setTargetFragment()
:
override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat?, pref: Preference): Boolean {
val args: Bundle = pref.extras
val fragment: Fragment = supportFragmentManager.fragmentFactory.instantiate(classLoader, pref.fragment)
fragment.arguments = args
supportFragmentManager.beginTransaction().replace(R.id.settings, fragment).addToBackStack(null).commit()
supportFragmentManager.setFragmentResultListener("requestKey") { key, bundle ->
if (key == "requestKey") {
// Get result from bundle
}
}
return true
}
And in your fragment that returns a result:
// Insert result in a bundle
setFragmentResult("requestKey", bundle)
Upvotes: 12