5

Ich implementiere BottomNavigationView für die Navigation in einer Android App. Ich verwende Fragmente, um den Inhalt für jede Registerkarte festzulegen.Getrennter Backstack für jede Registerkarte in BottomNavigationView Android mit Fragmenten

Ich weiß, wie Sie ein Fragment für jede Registerkarte einrichten und dann Fragmente wechseln, wenn auf eine Registerkarte geklickt wird. Aber wie kann ich einen separaten Backstack für jede Registerkarte haben? Hier ist der Code ein Fragment einzurichten:

Fragment selectedFragment = ItemsFragment.newInstance(); 
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 
transaction.replace(R.id.content, selectedFragment); 
transaction.commit(); 

Ein Beispiel Fragment A und B würde 1 und Fragment C und D unter Tab 2. Unter Tab werden, wenn die APP-Fragment A gestartet wird angezeigt und Tab 1 ist ausgewählt. Dann kann A durch Fragment B ersetzt werden. Wenn Tab 2 ausgewählt ist, sollte Fragment C angezeigt werden. Wenn Tab 1 dann ausgewählt wird, sollte Fragment B noch einmal angezeigt werden. An diesem Punkt sollte es möglich sein, die Zurück-Taste verwendet Fragment A.

zu zeigen, und hier ist der Code zum Einrichten nächste fragment in derselben Registerkarte: Methode

Fragment selectedFragment = ItemsFragment.newInstance(); 
FragmentTransaction ft = getFragmentManager().beginTransaction(); 
ft.replace(R.id.content, selectedFragment); 
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 
ft.addToBackStack(null); 
ft.commit(); 
+1

Unfortunatelly, werden Sie diese Art von Schnitt Backstack Verhalten implementieren müssen, um sich selbst ... glaube ich zumindest so. – Shark

+0

Hast du es schon mal gemacht? –

+0

Nein, meine Kunden wollten solch gebrochenes UX noch nie, aber ich habe eine Idee. Etwas zwischen dem aktuellen Backstack und der https: //en.wikipedia.org/wiki/Command_pattern Halten Sie eine 'HashMap ' und fügen Sie sie dem gewünschten Backstack hinzu. Erfordert Modifikationen der 'onBackPressed()' und vielleicht/wahrscheinlich nicht 'addToBackstack()' though. – Shark

Antwort

8

Schließlich habe ich die Lösung gefunden, es wurde von einer früheren Antwort auf Stackoverflow inspiriert: Separate Back Stack for each tab in Android using Fragments
ich habe nur TabHost mit BottomNavigationView ersetzt und hier ist der Code:
Hauptaktivität

public class MainActivity extends AppCompatActivity { 

private HashMap<String, Stack<Fragment>> mStacks; 
public static final String TAB_HOME = "tab_home"; 
public static final String TAB_DASHBOARD = "tab_dashboard"; 
public static final String TAB_NOTIFICATIONS = "tab_notifications"; 

private String mCurrentTab; 

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

    BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation); 
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); 

    mStacks = new HashMap<String, Stack<Fragment>>(); 
    mStacks.put(TAB_HOME, new Stack<Fragment>()); 
    mStacks.put(TAB_DASHBOARD, new Stack<Fragment>()); 
    mStacks.put(TAB_NOTIFICATIONS, new Stack<Fragment>()); 

    navigation.setSelectedItemId(R.id.navigation_home); 
} 

private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener 
     = new BottomNavigationView.OnNavigationItemSelectedListener() { 

    @Override 
    public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
     switch (item.getItemId()) { 
      case R.id.navigation_home: 
       selectedTab(TAB_HOME); 
       return true; 
      case R.id.navigation_dashboard: 
       selectedTab(TAB_DASHBOARD); 
       return true; 
      case R.id.navigation_notifications: 
       selectedTab(TAB_NOTIFICATIONS); 
       return true; 
     } 
     return false; 
    } 

}; 

private void gotoFragment(Fragment selectedFragment) 
{ 
    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); 
    fragmentTransaction.replace(R.id.content, selectedFragment); 
    fragmentTransaction.commit(); 
} 

private void selectedTab(String tabId) 
{ 
    mCurrentTab = tabId; 

    if(mStacks.get(tabId).size() == 0){ 
     /* 
     * First time this tab is selected. So add first fragment of that tab. 
     * Dont need animation, so that argument is false. 
     * We are adding a new fragment which is not present in stack. So add to stack is true. 
     */ 
     if(tabId.equals(TAB_HOME)){ 
      pushFragments(tabId, new HomeFragment(),true); 
     }else if(tabId.equals(TAB_DASHBOARD)){ 
      pushFragments(tabId, new DashboardFragment(),true); 
     }else if(tabId.equals(TAB_NOTIFICATIONS)){ 
      pushFragments(tabId, new NotificationsFragment(),true); 
     } 
    }else { 
     /* 
     * We are switching tabs, and target tab is already has atleast one fragment. 
     * No need of animation, no need of stack pushing. Just show the target fragment 
     */ 
     pushFragments(tabId, mStacks.get(tabId).lastElement(),false); 
    } 
} 

public void pushFragments(String tag, Fragment fragment, boolean shouldAdd){ 
    if(shouldAdd) 
     mStacks.get(tag).push(fragment); 
    FragmentManager manager = getSupportFragmentManager(); 
    FragmentTransaction ft = manager.beginTransaction(); 
    ft.replace(R.id.content, fragment); 
    ft.commit(); 
} 

public void popFragments(){ 
    /* 
    * Select the second last fragment in current tab's stack.. 
    * which will be shown after the fragment transaction given below 
    */ 
    Fragment fragment = mStacks.get(mCurrentTab).elementAt(mStacks.get(mCurrentTab).size() - 2); 

    /*pop current fragment from stack.. */ 
    mStacks.get(mCurrentTab).pop(); 

    /* We have the target fragment in hand.. Just show it.. Show a standard navigation animation*/ 
    FragmentManager manager = getSupportFragmentManager(); 
    FragmentTransaction ft = manager.beginTransaction(); 
    ft.replace(R.id.content, fragment); 
    ft.commit(); 
} 

@Override 
public void onBackPressed() { 
    if(mStacks.get(mCurrentTab).size() == 1){ 
     // We are already showing first fragment of current tab, so when back pressed, we will finish this activity.. 
     finish(); 
     return; 
    } 

    /* Goto previous fragment in navigation stack of this tab */ 
    popFragments(); 
} 

}

Startseite Fragment Beispiel

public class HomeFragment extends Fragment { 
@Nullable 
@Override 
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.fragment_home, container, false); 
    Button gotoNextFragment = (Button) view.findViewById(R.id.gotoHome2); 

    gotoNextFragment.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View view) { 
      ((MainActivity)getActivity()).pushFragments(MainActivity.TAB_HOME, new Home2Fragment(),true); 
     } 
    }); 
    return view; 
} 

}

+0

Aber wie speichern Sie den Zustand von HashMap über die Bildschirmdrehung? –

0

Anstelle der Verwendung ersetzen Verwenden Sie das Fragment hinzufügen,

Anstelle dieser Methode ft.replace (R.id.content, selectedFragment);

Verwenden Sie diese ft.add (R.id.content, selectedFragment);

Fragment selectedFragment = ItemsFragment.newInstance(); 
    FragmentTransaction ft = getFragmentManager().beginTransaction(); 
    ft.(R.id.content, selectedFragment); 
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 
    ft.addToBackStack(null); 
    ft.commit(); 
+1

mit Hinzufügen statt Ersetzen nicht funktioniert – Hanady

1

Es ist erwähnenswert, dass das von Ihnen beschriebene Verhalten gegen die Google-Richtlinien verstößt. https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior

Die Navigation durch die untere Navigationsleiste sollte den Aufgabenstatus zurücksetzen.

Mit anderen Worten, mit Fragment A und Fragment B "innen" Tab 1 ist in Ordnung, aber wenn der Benutzer Fragment B öffnet, klickt Tab 2, und klickt dann Tab 1 wieder, sie sollten Fragment A. siehe

+0

Instagram doesn ' t tun, dass sie den Backstack intakt halten, wenn Sie von einem Tab zum anderen gehen. –

Verwandte Themen