How to tell when fragment is not visible in a NavigationDrawer

蹲街弑〆低调 提交于 2020-01-01 19:21:32

问题


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...

  1. Use a consistent fragment, either Support or Native, not both. And, some say the Support fragment is preferable (better maintained).
  2. 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}).
  3. Do Use the Frament lifecycle events. onPause fires when you replace a fragment, so does onDetach. 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?
  4. 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 of setUserVisibleHint. 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, hence setUserVisibleHint was introduced.
  5. Bonus: If appropriate for your app, use the back stack for backing up by calling addToBackStack after replace. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!