2017-10-03 21 views
2

私は一日中答えを探していましたが、この質問に合った解決策は見つかりませんでした。Android BottomNavigationの適切なバックナビゲーションの実装方法

InstagramまたはPlayKioskアプリのようなBottomNavigationの使い方を作成する方法を探しています。フラグメントはバックスタックに1回だけ追加する必要があります。戻るボタンを押すと、訪問した最後のフラグメントと、そのFragmentに合うようにBottomNavigationのボタンにジャンプすることが期待されます。

現在、私は次のコードを使用し

//BottomNavigationListener 
private BottomNavigationView.OnNavigationItemSelectedListener buttonNavigationItemSelectedListener 
     = new BottomNavigationView.OnNavigationItemSelectedListener() { 

    @Override 
    public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
     FragmentManager fragmentManager = getSupportFragmentManager(); 
     switch (item.getItemId()) { 
      case R.id.navigation_game: 
       currentFragment = GameFragment.newInstance(); 
       fragmentManager.beginTransaction() 
         .addToBackStack(TAG_FRAGMENT_GAME) 
         .replace(R.id.content_frame, currentFragment, TAG_FRAGMENT_GAME) 
         .commit(); 
       break; 
      case R.id.navigation_tournament: 
       currentFragment = TournamentFragment.newInstance(); 
       fragmentManager.beginTransaction() 
         .addToBackStack(TAG_FRAGMENT_TOURNAMENT) 
         .replace(R.id.content_frame, currentFragment, TAG_FRAGMENT_TOURNAMENT) 
         .commit(); 
       break; 
      case R.id.navigation_history: 
       break; 
     } 
     return true; 
    } 

}; 

をしかし、これは私が私のBottomNavigationのボタンを数回押すと、このごとに新しいフラグメントがインスタンス化されるだろうクリックするという問題につながります。また、BottomNavigationボタンは、Fragmentsに従って設定されていません。

私はこの答えを見つけたが、それはあなたがInstagramのの同じ作業のロジックを持って次の構造を使用することができますPrevent The Same Fragment From Stacking More Than Once (addToBackStack)

+0

あなたはonBackPressed方法を扱うことができ、次のよう

public class LimitedUniqueQueue<E> extends LinkedList<E> { private int limit; public LimitedUniqueQueue(int limit) { this.limit = limit; } @Override public boolean add(E o) { // For uniqueness for (int i = 0; i < super.size(); i++) { E item = super.get(i); if (item.getClass() == o.getClass()) { super.remove(i); break; } } boolean added = super.add(o); // For size limit while (added && size() > limit) { super.remove(); } return added; } } 

その後、あなたの活動を更新しますか?最後のフラグメントを開いたままにしておき、戻るボタンを押すと、最後に読み込んだフラグメントを置き換えます。 –

答えて

0

をうまくいきませんでした。

まず、カスタムの限定ユニークキュークラスを作成します。最後のN個のアイテムのみを保持します.Nはコンストラクタに渡される制限数(または最大アイテム数)です。さらに、このタイプのキューはクラスのインスタンスを1つだけ保持します。クラスAのインスタンスがすでにキューにあり、クラスAの別のインスタンスがキューに追加される場合は、最初のインスタンスが最初に削除されてから新しいオブジェクトが挿入されます。

public class MainActivity extends AppCompatActivity { 

    private BottomNavigationView navigation; 
    private LimitedUniqueQueue<Fragment> queue; 
    ... 
    private BottomNavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener 
       = new BottomNavigationView.OnNavigationItemSelectedListener() { 

     Fragment gameFragment; 
     Fragment tournamentFragment; 
     Fragment profileFragment; 

     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 
      switch (item.getItemId()) { 
       case R.id.navigation_game: 
        if (gameFragment == null) { 
         gameFragment = new GameFragment(); 
        } 
        transaction.replace(R.id.content, gameFragment).commit(); 
        queue.add(gameFragment); 
        return true; 
       case R.id.navigation_tournament: 
        if (tournamentFragment == null) { 
         tournamentFragment = new TournamentFragment(); 
        } 
        transaction.replace(R.id.content, tournamentFragment).commit(); 
        queue.add(tournamentFragment); 
        return true; 
       case R.id.navigation_profile: 
        if (profileFragment == null) { 
         profileFragment = new ProfileFragment(); 
        } 
        transaction.replace(R.id.content, profileFragment).commit(); 
        queue.add(profileFragment); 
        return true; 
      } 
      return false; 
     } 

    }; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     navigation = (BottomNavigationView) findViewById(R.id.navigation); 
     queue = new LimitedUniqueQueue<>(navigation.getMenu().size()); 

     navigation.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener); 
     navigation.setSelectedItemId(R.id.navigation_game); 
     ... 
    } 

    @Override 
    public void onBackPressed() { 
     if (queue.size() > 1) { 
      queue.removeLast(); 
      Fragment previousFragment = queue.getLast(); 
      if (previousFragment instanceof GameFragment) { 
       navigation.setSelectedItemId(R.id.navigation_game); 
      } else if (previousFragment instanceof TournamentFragment) { 
       navigation.setSelectedItemId(R.id.navigation_tournament); 
      } else if (previousFragment instanceof ProfileFragment) { 
       navigation.setSelectedItemId(R.id.navigation_profile); 
      } 
     } else { 
      super.onBackPressed(); 
     } 
    } 

    ... 
} 
+0

誰でも試しましたか?私はそれがあなたのために働くのだろうか。 – Mehmed

+0

ちょうど今それをテストし、それは私のために正常に動作します。どうもありがとうございました。私が作った唯一の追加は、すでに新しいGameFragmentをonCreateのキューに追加して、開始時にキューに入れ、バックボタンを押したときのデフォルトのフォールバックとして追加することでした。 –

+0

ようこそ。 'onCreate()'メソッドで 'navigation.setSelectedItemId(R.id.navigation_game)'メソッドを呼び出して、起動時にGameFragmentを表示し、 'onNavigationItemSelected()'の 'queue'に暗黙的に追加します。いずれにせよ、私はそれがうまくいってうれしいです。 – Mehmed

関連する問題