问题
I am trying to tell when a user selects a different fragment in my navigation drawer. I was trying to use
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
}
How i switch fragments in my MainActivity:
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
R.id.nav_camera -> {
// Handle the camera action
val fragment: HomeFragment = HomeFragment()
supportFragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit()
}
R.id.nav_manage -> {
val fragment: SettingFragment = SettingFragment()
fragmentManager.beginTransaction().replace(R.id.content_main, fragment).commit()
}
R.id.nav_share -> {
onInviteClicked()
}
R.id.nav_send -> {
val emailIntent: Intent = Intent(android.content.Intent.ACTION_SEND)
emailIntent.type = Constants.FEEDBACK_EMAIL_TYPE
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
arrayOf(Constants.FEEDBACK_EMAIL_ADDRESS))
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
Constants.FEEDBACK_EMAIL_SUBJECT)
startActivity(Intent.createChooser(
emailIntent, Constants.FEEDBACK_TITLE))
}
}
val drawer: DrawerLayout = findViewById(R.id.drawer_layout)
drawer.closeDrawer(GravityCompat.START)
return true
}
However this does not seem to get called at all. For example, in my NavigationDrawer
activity, it shows Fragment A. The user opens the navigation drawer and selects Fragment B. setUserVisibleHint()
does not get called in fragment A so my code can know it is no longer shown. I need my code that is isolated in fragment A to know when it is not shown so it can call .stop() on some variables. This is the same use case as onPause() in an activity.
回答1:
Here are a few things I can think of...
- Use a consistent fragment, either Support or Native, not both. And, some say the Support fragment is preferable (better maintained).
- Make sure the fragment container is not hard coded in XML. If you intend to replace a fragment, then the initial fragment should be loaded dynamically by your code (you typically will load into a FrameLayout using the id as your R.id.{frameLayoutId}).
- Do Use the Frament lifecycle events.
onPause
fires when you replace a fragment, so doesonDetach
. That will tell you when your old fragment is no longer visible (or will be invisible shortly). If it does not fire, then you have another issue in your code, possibly mixing of Fragment types, or a hardcoded fragment in XML? - Use
setUserVisibleHint
only in a fragment pager, or be prepared to set it manually. this answer has a little more to say about the use ofsetUserVisibleHint
. When using a pager, multiple fragments can be attached at once, so an additional means (some call it lifecycle event) was needed to tell if a fragment was "really, truly" visible, hencesetUserVisibleHint
was introduced. Bonus: If appropriate for your app, use the back stack for backing up by calling
addToBackStack
afterreplace
. I add this mainly as an addition lifecycle item one would typically want in their app. The code looks like this...// to initialize your fragment container supportFragmentManager .beginTransaction() .add(R.id.content_fragment, fragment) .addToBackStack("blank") .commit() // to update your fragment container supportFragmentManager .beginTransaction() .replace(R.id.content_fragment, fragment) .addToBackStack("settings") .commit() //in your XML, it can be as simple as adding the FrameLayout below, // if you start with the Android Studio template for Navigation drawer, // you can replace the call that includes the "content_main" layout <!--<include layout="@layout/content_main" /> --> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/content_fragment" />
I hope this helps.
回答2:
You can simply call
if (myFragment.isVisible()) {...}
or another way is
public boolean isFragmentUIActive() {
return isAdded() && !isDetached() && !isRemoving();
}
回答3:
Keep a global variable activeFragment
.
When a user clicks on a fragment, set activeFragment
to that fragment.
...
val fragment: HomeFragment = HomeFragment()
activeFragment = HomeFragment
...
val fragment: SettingFragment = SettingFragment()
activeFragment = SettingFragment
Then,
if(FragmentA != activeFragment) {
//Call stop here
}
来源:https://stackoverflow.com/questions/45269174/how-to-tell-when-fragment-is-not-visible-in-a-navigationdrawer