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 
}