2017-07-16 133 views
1

我想在我的項目中創建一個底部導航欄。每個視圖都有它自己的片段。問題是,每次我點擊按鈕來改變視圖,例如從最近到最喜歡它創建新的片段與全新的狀態(例如,滾動位置,文字改變我的片段包含)。我知道在官方的Android文檔中寫道,底部的導航欄應該重置任務狀態,但我認爲這對用戶來說太不舒服。 我想有一種類似的功能,如Instagram,你從飼料改變到探索和回滾飼料的滾動位置圖像緩存一切仍然保存。我幾乎想通過各種方式解決這個問題,唯一有效的方法是通過設置可見性GONE並根據情況設置可見性VISIBLE,但我知道這不是正確的方法,應該有更好的方法來做到這一點,我不是在說手動節省需要的實例。我幾乎跟隨了關於底部導航片段的所有教程,但有趣的是,沒有人有興趣在不每次調用新的情況下使用它。BottomNavigationView - 如何避免片段的重新創建並重用它們

enter image description here

enter image description here

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
fragmentTransaction.replace(R.id.frameLayout, FirstFragment.newInstance()); 
fragmentTransaction.commit(); 

bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation); 
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { 
    @Override 
    public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
     Fragment fragment = null; 
     switch (item.getItemId()) { 
      case R.id.menu_dialer: 
       fragment = FirstFragment.newInstance(); 
       break; 
      case R.id.menu_email: 
       fragment = SecondFragment.newInstance(); 
       break; 
      case R.id.menu_map: 
       fragment = ThirdFragment.newInstance(); 
       break; 
     } 
     if (fragment != null) { 
      FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
      fragmentTransaction.replace(R.id.frameLayout, fragment); 
      fragmentTransaction.commit(); 
     } 
     return true; 
    } 
}); 

我也試過onAttach和Deattach解決方案,而且又沒有成功。

VIDEO LINK : new i tried Nino Handler version it only works when i tap on the same fragment button

也許連接,我用我的gradle產出依賴金絲雀版本還是出問題了嗎? enter image description here

NEW UPDATES:

最新更新:

public class MainActivity extends AppCompatActivity { 

    private TextView mTextMessage; 


    private static final String TAG_FRAGMENT_ONE = "fragment_one"; 
    private static final String TAG_FRAGMENT_TWO = "fragment_two"; 

    private FragmentManager fragmentManager; 
    private Fragment currentFragment; 

    String TAG = "babken"; 
    private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener 
      = new BottomNavigationView.OnNavigationItemSelectedListener() { 

     Fragment fragment = null; 
     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
      switch (item.getItemId()) { 
       case R.id.navigation_home: 
        fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE); 
        if (fragment == null) { 
         fragment = FragmentFirst.newInstance(); 
        } 
        replaceFragment(fragment, TAG_FRAGMENT_ONE); 

        break; 
       case R.id.navigation_dashboard: 

        fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO); 
        if (fragment == null) { 
         fragment = FragmentSecond.newInstance(); 
        } 
        replaceFragment(fragment, TAG_FRAGMENT_TWO); 

        break; 
      } 
      return true; 

     } 
    }; 

    private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) { 
     if (!fragment.equals(currentFragment)) { 
      fragmentManager 
        .beginTransaction() 
        .replace(R.id.armen, fragment, tag) 
        .commit(); 
      currentFragment = fragment; 
     } 
    } 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     fragmentManager = getSupportFragmentManager(); 
     Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE); 
     if (fragment == null) { 
      fragment = FragmentFirst.newInstance(); 
     } 
     replaceFragment(fragment, TAG_FRAGMENT_ONE); 
     BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation); 
     navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); 
    } 

} 

回答

1

所以,我一直在研究這個很長一段時間,想通了,有沒有辦法重用你必須保存自動保存狀態片段您需要的狀態手動然後檢索它們,每當一個新的片段創建,但滾動的位置如何太難,甚至在某些情況下,不可能保存滾動視圖的位置狀態(例如回收者視圖)。所以我使用了被稱爲VISIBILITY的概念,當我點擊按鈕時,片段變得可見,其他人自動隱藏。如果有人需要更詳細的解釋關於VISIBILITY.VISIBLEVISIBILITY.GONE評論我會通過細節。

+0

嗨,我有完全相同的問題..你能給我一些關於解決方案或一些代碼的細節嗎? – 2017-11-30 11:39:31

+0

你的問題在你自己的問題上工作嗎?我也有同樣的問題。 @ArmenHovhannisian – TiagoIB

0

怎麼樣。 You 在該類中聲明片段

Fragment firstFragment,secondFragment,thirdFragment; 

然後在的switch-case您可以編寫爲:

switch (item.getItemId()) { 
    case R.id.menu_dialer: 
     if(firstFragment != null) { 
      fragment = firstFragment; 
     }else{ 
      fragment = FirstFragment.newInstance(); 
     } 
     break; 
    case R.id.menu_email: 
     // the same ... 
     break; 
    case R.id.menu_map: 
     //the same ... 
     break; 
} 
+1

我試過這個,但讓我再次檢查,也許我錯過了一些東西。 –

+0

每次它創建新的片段 –

0

創建三個片段作爲類的成員,並重新使用它們。

public class MainActivity extends AppCompatActivity { 
    private final Fragment mFirstFragment = new FirstFragment(); 
    private final Fragment mSecondFragment = new SecondFragment(); 
    private final Fragment mThirdFragment = new ThirdFragment(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     ...... 
     ...... 
     FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
     fragmentTransaction.replace(R.id.frameLayout, mFirstFragment); 
     fragmentTransaction.commit(); 

     bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { 
      @Override 
      public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
       if (bottomNavigationView.getSelectedItemId() != item.getItemId()) { 
        switch (item.getItemId()) { 
         R.id.menu_dialer: 
          replaceFragment(mFirstFragment); 
          break; 
         case R.id.menu_email: 
          replaceFragment(mSecondFragment); 
          break; 
         case R.id.menu_map: 
          replaceFragment(mThirdFragment); 
          break; 
        } 
       } 
       return true; 
      } 
     }); 
    } 

    private void replaceFragment(Fragment fragment) { 
     FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
     fragmentTransaction.replace(R.id.frameLayout, fragment); 
     fragmentTransaction.commit(); 
    } 

} 
+0

甚至沒有嘗試它很明顯,它會創建新的片段。 –

+0

是的,但只有一次。 – kws

+0

但爲什麼只有每次點擊一次,它纔會到達該方法,並在那裏獲取片段並再次創建新片段。 –

1

我不會保留全局的片段實例。 而不是創建他們

getSupportFragmentManager() 
      .beginTransaction() 
      .replace(R.id.container, new PlaceholderFragment(), TAG_PLACEHOLDER) 
      .commit(); 

然後,當一個標籤添加到片段,你可以隨時取回它像這樣:

Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG_PLACEHOLDER); 
    if (fragment == null) { 
     fragment = new PlaceholderFragment(); 
    } 
    getSupportFragmentManager() 
      .beginTransaction() 
      .replace(R.id.container, fragment, TAG_PLACEHOLDER) 
      .commit(); 

更新:我更新了我的答案,並提供了完整的解決方案:

private static final String TAG_FRAGMENT_ONE = "fragment_one"; 
private static final String TAG_FRAGMENT_TWO = "fragment_two"; 
private static final String TAG_FRAGMENT_THREE = "fragment_three"; 

private FragmentManager fragmentManager; 
private Fragment currentFragment; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // instantiate the fragment manager 
    fragmentManager = getSupportFragmentManager(); 

    Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE); 
    if (fragment == null) { 
     fragment = FirstFragment.newInstance(); 
    } 
    replaceFragment(fragment, TAG_FRAGMENT_ONE); 

    bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation); 
    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() { 
     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
      Fragment fragment = null; 
      switch (item.getItemId()) { 
       case R.id.menu_dialer: 
        // I'm aware that this code can be optimized by a method which accepts a class definition and returns the proper fragment 
        Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_ONE); 
        if (fragment == null) { 
         fragment = FirstFragment.newInstance(); 
        } 
        replaceFragment(fragment, TAG_FRAGMENT_ONE); 
        break; 
       case R.id.menu_email: 
        Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_TWO); 
        if (fragment == null) { 
         fragment = SecondFragment.newInstance(); 
        } 
        replaceFragment(fragment, TAG_FRAGMENT_TWO); 
        break; 
       case R.id.menu_map: 
        Fragment fragment = fragmentManager.findFragmentByTag(TAG_FRAGMENT_THREE); 
        if (fragment == null) { 
         fragment = ThirdFragment.newInstance(); 
        } 
        replaceFragment(fragment, TAG_FRAGMENT_THREE); 
        break; 
      } 
      return true; 
     } 
    }); 
} 

private void replaceFragment(@NonNull Fragment fragment, @NonNull String tag) { 
    if (!fragment.equals(currentFragment)) { 
     fragmentManager 
      .beginTransaction() 
      .replace(R.id.frameLayout, fragment, tag) 
      .commit(); 
     currentFragment = fragment; 
    } 
} 

其他信息:如果您想確保片段狀態不會改變,並且您還想要能夠滑動片段,則應考慮使用ViewPagerFragmentStatePagerAdapter,改變當前片段中的適配器每次點擊事件

+0

我試過了,我把問題底部的鏈接檢查出來 –

+0

你使用3個不同的標籤? –

+0

我該如何向您發送個人信息to.show my.code? –

相關問題