nawigacja w górę paska czynności z fragmentami

Mam tabbed ActionBar / ViewPager layout z trzema zakładkami say A, B i C . W zakładce C tab (fragment) dodaję kolejny fragment powiedzmy fragment D . z

 DFragment f= new DFragment();
 ft.add(android.R.id.content, f, "");
 ft.remove(CFragment.this);
 ft.addToBackStack(null);
 ft.commit();

Modyfikowałem actionbar w dfragment ' s onResume, aby dodać przycisk:

ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);

Teraz w DFragment, po naciśnięciu przycisku hardware(phone) Back, wracam do oryginalnego układu z kartami (ABC) z zaznaczonym CFragment. Jak mogę osiągnąć tę funkcjonalność za pomocą actionbar up guzik?

Author: QED, 2012-10-26

9 answers

Zaimplementuj OnBackStackChangedListener i dodaj ten kod do swojej aktywności Fragment.

@Override
public void onCreate(Bundle savedInstanceState) {
    //Listen for changes in the back stack
    getSupportFragmentManager().addOnBackStackChangedListener(this);
    //Handle when activity is recreated like on orientation Change
    shouldDisplayHomeUp();
}

@Override
public void onBackStackChanged() {
    shouldDisplayHomeUp();
}

public void shouldDisplayHomeUp(){
   //Enable Up button only  if there are entries in the back stack
   boolean canback = getSupportFragmentManager().getBackStackEntryCount()>0;
   getSupportActionBar().setDisplayHomeAsUpEnabled(canback);
}

@Override
public boolean onSupportNavigateUp() {
    //This method is called when the up button is pressed. Just the pop back stack.
    getSupportFragmentManager().popBackStack();
    return true;
}
 168
Author: Roger Garzon Nieto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-17 13:09:27

Zajmę się tym. wystarczy zastąpić onOptionsItemSelected w aktywności hostingowej i popup backstack, np.

public boolean onOptionsItemSelected(MenuItem item) {

  switch (item.getItemId()) {
   case android.R.id.home:
     FragmentManager fm = getSupportFragmentManager();
     if (fm.getBackStackEntryCount() > 0) {
          fm.popBackStack();
        }
        return true;
    default:
        return super.onOptionsItemSelected(item);;
    }
}

Wywołaj getActionBar().setDisplayHomeAsUpEnabled(boolean); i getActionBar().setHomeButtonEnabled(boolean); w onBackStackChanged(), Jak wyjaśniono w Odpowiedzi poniżej.

 36
Author: SohailAziz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-26 19:25:00

Jeśli masz jedną aktywność rodzica i chcesz, aby ten przycisk w górę działał jako przycisk Wstecz, możesz użyć tego kodu:

Dodaj to do onCreate w swojej głównej klasie aktywności

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
            if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment)
                getSupportActionBar().setHomeButtonEnabled(true);
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            } else {
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                getSupportActionBar().setHomeButtonEnabled(false);
            }
        }

    });

A następnie dodać onOptionsItemSelected TAK:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
     ....
 }

Ogólnie używam tego cały czas i wydaje się całkiem legalne

 18
Author: Daniel Jonker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-22 03:31:01

Możesz wrócić z Przyciskiem w górę jak przycisk Wstecz;

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}
 9
Author: Moaz Rashad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-23 16:29:29

Użyłem kombinacjiRoger Garzon Nieto 'S isohailaziz' S odpowiedzi. Moja aplikacja ma jedną główną aktywność i ładowane do niej fragmenty A, B, C. Mój" domowy " fragment (a) implementuje OnBackStackChangedListener i sprawdza rozmiar backstacka; jeśli jest mniejszy niż jeden, to ukrywa przycisk w górę. Fragmenty B I C zawsze ładują przycisk Wstecz (w moim projekcie B jest uruchamiany Z A, A C z B). Sam główny po prostu wyskakuje na tył dotknij przycisku i ma metody wyświetlania / ukrywania przycisku, które wywołują fragmenty:

Główna aktywność:

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

public void showUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); }
public void hideUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); }

FragmentA (implementuje FragmentManager.OnBackStackChangedListener):

public void onCreate(Bundle savedinstanceSate) {
    // listen to backstack changes
    getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this);

    // other fragment init stuff
    ...
}

public void onBackStackChanged() {
    // enable Up button only  if there are entries on the backstack
    if(getActivity().getSupportFragmentManager().getBackStackEntryCount() < 1) {
        ((MainActivity)getActivity()).hideUpButton();
    }
}

FragmentB, fragmentC:

public void onCreate(Bundle savedinstanceSate) {
    // show the UP button
    ((MainActivity)getActivity()).showUpButton();

    // other fragment init stuff
    ...
}
 5
Author: verboze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:03

Wiem, że to pytanie jest stare, ale może ktoś (jak ja) też go potrzebuje.

Jeśli Twoja aktywność rozszerza AppCompatActivity , możesz użyć prostszego (dwustopniowego) rozwiązania:

1-za każdym razem, gdy dodajesz fragment spoza domu, po prostu pokaż przycisk w górę, zaraz po zatwierdzeniu transakcji fragment. TAK:

    // ... add a fragment
    // Commit the transaction
    transaction.commit();

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

2 - po naciśnięciu przycisku w górę, chowasz go.

@Override
public boolean onSupportNavigateUp() {
    getSupportActionBar().setDisplayHomeAsUpEnabled(false);        
    return true;
}
To wszystko.
 5
Author: Marcos Tomasello,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-05 19:56:41

To mi pomogło. Override onSupportNavigateUp i onBackPressed, na przykład (kod w Kotlinie);

override fun onBackPressed() {
    val count = supportFragmentManager.backStackEntryCount
    if (count == 0) {
        super.onBackPressed()
    } else {
        supportFragmentManager.popBackStack()
    }
}

override fun onSupportNavigateUp(): Boolean {
    super.onSupportNavigateUp()
    onBackPressed()
    return true
}

Teraz we fragmencie, jeśli wyświetlisz strzałkę w górę

activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)

Kliknięcie na niego przenosi cię z powrotem do poprzedniej aktywności.

 3
Author: Chidi Chris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-31 13:14:24

To bardzo dobre i niezawodne Rozwiązanie: http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/

Facet stworzył abstrakcyjny fragment, który zajmuje się zachowaniem backPress i przełącza się między aktywnymi fragmentami za pomocą wzorca strategii.

Dla niektórych z was to może mała wada w klasie abstrakcyjnej...

Wkrótce rozwiązanie z linku wygląda tak:

// Abstract Fragment handling the back presses

public abstract class BackHandledFragment extends Fragment {
    protected BackHandlerInterface backHandlerInterface;
    public abstract String getTagText();
    public abstract boolean onBackPressed();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(!(getActivity()  instanceof BackHandlerInterface)) {
            throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
        } else {
            backHandlerInterface = (BackHandlerInterface) getActivity();
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        // Mark this fragment as the selected Fragment.
        backHandlerInterface.setSelectedFragment(this);
    }

    public interface BackHandlerInterface {
        public void setSelectedFragment(BackHandledFragment backHandledFragment);
    }
}   

I użycie w aktywność:

// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS 
// IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment

public class TheActivity extends FragmentActivity implements BackHandlerInterface {
    private BackHandledFragment selectedFragment;

    @Override
    public void onBackPressed() {
        if(selectedFragment == null || !selectedFragment.onBackPressed()) {
            // Selected fragment did not consume the back press event.
            super.onBackPressed();
        }
    }

    @Override
    public void setSelectedFragment(BackHandledFragment selectedFragment) {
        this.selectedFragment = selectedFragment;
    }
}
 2
Author: zatziky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-03 12:05:22

Kotlin:

class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        supportFragmentManager.addOnBackStackChangedListener { setupHomeAsUp() }
        setupHomeAsUp()
    }

    private fun setupHomeAsUp() {
        val shouldShow = 0 < supportFragmentManager.backStackEntryCount
        supportActionBar?.setDisplayHomeAsUpEnabled(shouldShow)
    }

    override fun onSupportNavigateUp(): Boolean = 
        supportFragmentManager.popBackStack().run { true }

    ...
}
 1
Author: fada21,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-29 17:11:37