1

我试图告诉用户何时在我的导航抽屉中选择不同的片段。我试图用如何判断片段在NavigationDrawer中不可见

override fun setUserVisibleHint(isVisibleToUser: Boolean) { 
    super.setUserVisibleHint(isVisibleToUser) 
} 

我如何在我的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 
    } 

然而,这似乎并没有得到所谓的。例如,在我的NavigationDrawer活动中,它显示片段A.用户打开导航抽屉并选择片段B. setUserVisibleHint()未在片段A中调用,因此我的代码可以知道它不再显示。我需要我的代码在片段A中被隔离,以便知道它何时不显示,因此它可以在某些变量上调用.stop()。这与活动中的onPause()具有相同的用例。

+0

我不明白你的问题。为什么不直接使用导航抽屉?我的意思是,你知道用户已经选择了片段B,所以你知道发生了什么。那么不要把你的逻辑放在Navigation Drawer的onClickListener中。就像那样,你会知道什么是显示或不显示,而不会从片段的状态中猜出它。但是你确定你的片段A不是随便显示的吗? 你有导航抽屉监听器的代码吗? – Eselfar

+1

请发布更多的代码,你在哪里调用这个函数?你的活动是什么样子的? – Derek

+0

@Eselfar我已经添加了更多的信息,为什么我需要它这样。 –

回答

2

这里有几件事情我能想到的...

  1. 使用一致的片段,无论是支持还是本地人,不能同时使用。而且,有人说支持片段更好(维护得更好)。
  2. 确保片段容器不是用XML硬编码的。如果你打算替换一个片段,那么最初的片段应该被你的代码动态加载(你通常会使用id作为你的R.id. {frameLayoutId})加载到一个FrameLayout中。
  3. 请使用 Frament生命周期事件。 在替换片段时触发,因此onDetach也会触发。这会告诉你什么时候你的旧片段不再可见(或者很快就会隐形)。如果它没有触发,那么你的代码中有另一个问题,可能是混合了片段类型,或者是XML中的硬编码片段?
  4. 仅在片段寻呼机中使用setUserVisibleHint,或者准备手动设置。 this答案有更多关于使用setUserVisibleHint的说法。当使用寻呼机时,可以一次连接多个片段,因此需要额外的手段(有些人称之为生命周期事件)来确定片段是否“真正地,真正”可见,因此引入了setUserVisibleHint
  5. 红利:如果适合您的应用程序,请在replace之后拨打addToBackStack以备用备份。我主要将它添加为人们通常希望在其应用程序中添加的生命周期项目。该代码看起来像这样...

    // 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" /> 
    

我希望这有助于。

+0

我会添加专门使用PreferenceFragmentCompat与supportfragmentmanager一起使用。这是我使用Native和Support片段管理器的问题 –

2

你可以简单地调用

if (myFragment.isVisible()) {...} 

或另一种方式是

public boolean isFragmentUIActive() { 
    return isAdded() && !isDetached() && !isRemoving(); 
} 
+0

因为这不是一个重写方法,我将不得不有一个无限循环不断检查片段是否可见,这不会是理想的。 –

0

保持一个全局变量activeFragment。 当用户点击一个片段时,将activeFragment设置为该片段。

... 
val fragment: HomeFragment = HomeFragment() 
activeFragment = HomeFragment 

... 
val fragment: SettingFragment = SettingFragment() 
activeFragment = SettingFragment 

然后,

if(FragmentA != activeFragment) { 
    //Call stop here 
}