android: ¿Al presionar el botón de retroceso regresar a el anterior fragment?

Tengo múltiples fragments [1],[2],[3], al estar en cualquiera de ellos y presionar el botón de retroceso me saca de la aplicación. Que debo hacer para que en vez de que me saque de la aplicación, regrese al fragment anterior. De antemano gracias.

En mi actividad principal (es un drawer menu) invoco el fragment así:

fragmentManager.beginTransaction().replace(R.id.content_frame,new SearchFragment()).commit();

En esta misma actividad tengo el método que se acciona al presionar el botón de retroceso

  @Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0) {
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}
4
задан 12.10.2016, 23:59
5 ответов

Очень хорошо, я помещаю тебе пример, как я этим манипулировал, что я помнил, если я функционировал, и нажав back он возвращал меня в fragment предыдущий:

В методе, который он позволяет выбирать items внутри NavigationDrawer ты добавляешь его .addToBackStack(null) перед .commit(); в каждый из них, пример:

 @Override
    public void onNavigationDrawerItemSelected(int position) {
        //Este método controla los llamados a los botones del Drawer.
        // Actualiza el contenido principal sustituyendo el fragment
        FragmentManager fragmentManager = getSupportFragmentManager();

        switch (position) {
            case 0:
                fragmentManager.beginTransaction()
                        .replace(R.id.container, MainScreenSubView.newInstance(position + 1))
                        .commit();
                break;
            case 1:
                fragmentManager.beginTransaction()
                        .replace(R.id.container, new ChatView()).addToBackStack(null)
                        .commit();
                break;
            case 2:
                fragmentManager.beginTransaction()
                        .replace(R.id.container, new PremiumView()).addToBackStack(null)
                        .commit();
                break;
            case 3:
                fragmentManager.beginTransaction()
                        .replace(R.id.container, new AboutView()).addToBackStack(null)
                        .commit();
                break;
            case 4:
                UserModel.instance().logout();
                System.exit(0);
                finish();
        }
    }

ЗАМЕТЬ: Не предусмотри в оставшуюся часть кода, только я скопировал и прикрепил с моего repo :P

В методе onBackPressed() ты это оставляешь следующего способа (Он неполный, но как явись функциональным :P):

@Override
    public void onBackPressed() {

        int count = getFragmentManager().getBackStackEntryCount();

        if (count == 0) {
            super.onBackPressed();
            getFragmentManager().popBackStack();
        } else {
             getFragmentManager().popBackStack();//No se porqué puse lo mismo O.o
        }

    }
2
ответ дан 24.11.2019, 13:09
  • 1
    Спасибо за твой ответ x4mp73r, у меня вопрос есть, в каждый fragment не нужно помещать какое-то преподавание, чтобы мочь возвращаться?. Например из fragment я перехожу с другим fragment, потом нажимаю retroseso, он был бы должен возвращаться к anterioir fragment. – devjav 11.10.2016, 17:29
  • 2
    Мой этот очень ясный ответ: D, прочитай весь и старайся уподоблять ее, .addToBackStack(null) с этим перед commit(); в каждых женил , так как внутри них я делаю названный в fragments , которые внутри Drawer названы статьями и экспертом и # 237; поскольку у меня есть м и # 233; совсем back функционирует, и #191; он и # 237; do мой ответ? – x4mp73r 11.10.2016, 17:32
  • 3
    Конечно же я смотрел твой ответ, которому он предпочитал меня, дело в том, что, как кажется, возвратившись к anterioir fragment, он вновь не инициализирует а именно, он вновь не создает вид (он не выполняет снова onCreateView) – devjav 11.10.2016, 17:53
  • 4
    Так как тот, кто знает, как это у тебя было, потому что я c и # 243; я говорю, что он это делает: С Main (Что первым, что он появляется, является drawer) я выбираю статью, которую я хочу, давайте говорить About , despu и # 233; s я ввожу men и # 250; и клик в Чат , despu и # 233; s возвращение и он показывает мне fragment About , возвращение и посылает меня главной, это все то, что он делает я c и # 243; я говорю, не необходимо размещать в каждых fragment_como ты думаешь, это добавляет в каждый _case из Drawer , это целиком с м и # 233; каждый back они способствуют тому, чтобы оно функционировало. – x4mp73r 11.10.2016, 18:00
  • 5
    У меня есть забытый app (неудавшийся проект) в Плаи Сторе, где я использую c и # 243; я говорю, что я показываю тебя, не уверен, если в и # 250; n функционировали серверы начал sesi и # 243; n, но пробуй, и если оно функционирует ты давать и # 225; s расскажи, как оно функционирует play.google.com/store/apps/details?id=mx.appco.appbogado – x4mp73r 11.10.2016, 18:06

Ты нуждаешься в том, чтобы добавить это к back stack FragmentManager

    fragmentManager
            .beginTransaction()
            .replace(R.id.content_frame, new SearchFragment())
            .addToBackStack(null)
            .commit();
2
ответ дан 24.11.2019, 13:09

Для этого лучший выбор состоял бы в том, чтобы использовать .add вместо .replace то, что он делает .add он состоит в том, чтобы складывать в штабели тебе фрагменты и это делает, что, когда ты дашь back, возвращаются в предыдущего, без необходимости делать другой "прием"

MiFragment miFragment = MiFragment.newInstance();
        mFragmentManager.beginTransaction()
                .add(R.id.container, miFragment, "fragment_tag") // <-
                .addToBackStack(null)
                .commit();

backpressed делается на активности и не на fragment..., так что в активности ты можешь делать это:

@Override
public void onBackPressed() {
    if (mFragmentManager.getBackStackEntryCount() > 1
       mFragmentManager.popBackStack();
    else{
       finish();
    }
} 

Метод getBackStackEntryCount() ты переземляника candidad фрагментов, которые сложены в штабели в настоящее время. Тогда, если candidad fragments в батарейке они больше, один идет происходить с предыдущим, если уже нет больше, он закончит с активностью, что этот contendiendo :D

1
ответ дан 24.11.2019, 13:09

Первое, что ты должен делать, - sobrescribir метод onBackPressed(){...} твоего главного Activity, или который будет содержать все Fragments, это чтобы, в момент нажимать на кнопку back, ты смог настраивать действие, которое реализует твое приложение.

@Override
public void onBackPressed() {

   //si no queda ningún fragment sale de este activity
    if (getFragmentManager().getBackStackEntryCount() == 0) {
     // super.onBackPressed(); 
        finish();

    } else { //si no manda al fragment anterior.
        getFragmentManager().popBackStack();
    }
}

После в каждый Layout ты должен добавлять идентификацию в Вашем определении. Этот layout назван классом Fragment1, который он увеличивает Fragment

Когда ты захочешь открыть нового Frament с тебя Activity, ты будешь должен добавлять это в FragmentManager следующей формы:

                    //Si deseas pasar información entre Framgnets
                    Bundle args = new Bundle();
                    args.putString("Param1", Value);

        //Declaramos el nuevo Fragment que queremos abrir                       
                     FragmentManager fm  = getFragmentManager();
                     Fragment newFragment= new Fragment1();
                     newFragment.setArguments(args); //agregamos la informacion

                     //Agregamos el Fragment a la lista. content_frame es el lugar en tu Activity donde se mostrarán los framgnetes
                 fm.beginTransaction()
                        .add(R.id.content_frame, newFragment)
                        .commit();

Если ты хочешь открыть нового Fragment с другого Fragment вещь продолжает быть тем же самым, предполагая, что ты в Fragment1 и хочешь открыть Fragment 2, создаешь ты Layout и твой класс для Framgnet2

                    Fragment newFragment = new Fragment2();                    
                    FragmentTransaction transaction = getFragmentManager().beginTransaction();

        //Agregamos el Fragment al BackStack
                    transaction.replace(R.id.Fragment1, newFragment);
                    transaction.addToBackStack("Fragment1");
                    transaction.commit();

И с этим ты гарантируешь навигацию между Fragments.

1
ответ дан 24.11.2019, 13:09

Главный файл навигации между фрагментами:

Мои заключения на теме навигации между фрагментами, перед всем ты должен располагать в порядке хорошо глубину навигации, если она очень изысканная, пользователь может терять ориентацию навигации.

Гид google на главном файле навигации Обобщая: В приложении, составленном двумя типами содержимого libros и películas у него может быть каждый un listado и одна vista de detalle, в виде детали фильма он мог бы рекомендовать тебе Вашу книгу или наоборот.

Доступные фрагменты:

Прямой доступ с бокового меню:

  • Главный
  • Занеси в список книги
  • Занеси в список фильмы

Без прямого доступа в боковом меню:

  • Деталь освободила
  • Подробно опишите фильм

Давайте помещать, что действие пользователя реализует:

Principal -> Listar libros -> Listar películas -> Detalle película 

(3 возврата)

Principal -> Listar libros -> Listar películas -> Detalle película -> Detalle libro

(4 возврата)

Оставаясь главный файл, который Google рекомендует, когда она явится деталью книги, отступив, я поместил в списке книг:

Detalle libro -> listado de libros -> principal 

(3 возврата перед 4), Но не быть, если это лучшее это, так как пользователь может удивляться, что открывают ему список книг нежели деталь фильма, если он хочет занести в список книги, уже имеет прямое действие по отношению к боковому меню.

Чтобы улучшать usuabilidad навигации начиная с последнего примера, он изменил бы батарейку для того, чтобы только было 3 возврата, исключая заносить в список книги.

Оставаясь таким:

Principal -> Listar películas -> Detalle película -> Detalle libro

(3 возврата перед 4)

Рисунок навигации:

  • Первый фрагмент загружать это с add так, когда это последний, он выходит из app.
  • Создавать батарейку, где будут сохранять фрагменты: addToBackStack(TAG)
  • Чтобы получать все фрагменты есть в батарейке: getBackStackEntryCount()
  • Действие отступать, удалять последний фрагмент батарейки: popBackStack()
  • Удалять батарейку, если пользователь использует боковое меню, чтобы помещаться в начало.
  • Предотвращать удвоение фрагмента в батарейке, нужно избавлять это.

Фрагмент доказательства

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class FragmentA extends Fragment {
    private static final String ARG_ID = "param_id";
    private static final String ARG_TITLE = "param_title";
    private static final String TAG = FragmentA.class.getSimpleName();

    private int mParam1;
    private String mParam2;


    public FragmentA() {
    }

    public static FragmentA newInstance(int param1, String param2) {
        FragmentA fragment = new FragmentA();
        Bundle args = new Bundle();
        args.putInt(ARG_ID, param1);
        args.putString(ARG_TITLE, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getInt(ARG_ID);
            mParam2 = getArguments().getString(ARG_TITLE);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_blank, container, false);

    //Al rescatar de la pila necesario resaltar el menu y cambiar el texto
    NavigationView navigationView = (NavigationView) getActivity().findViewById(R.id.nav_view);
    navigationView.getMenu().findItem(mParam1).setChecked(true);
    getActivity().setTitle(mParam2);


        TextView tvLabel = (TextView) view.findViewById(R.id.label);
        tvLabel.setText(mParam2);

        Log.d(TAG, "onCreateView: " + mParam1 + " " + mParam2);

        return view;
    }

}

Система навигации

В onNavigationItemSelected он, где ты должен решать, что элементы меню он должен загружать один fragmento или одна activdad

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {

    Fragment newFragment = null;

    int id = item.getItemId();

    if (id == R.id.nav_camera) {
        newFragment = FragmentA.newInstance(id, item.getTitle().toString());
    } else if (id == R.id.nav_gallery) {
        newFragment = FragmentB.newInstance(id, item.getTitle().toString());
    } else if (id == R.id.nav_slideshow) {
        newFragment = FragmentC.newInstance(id, item.getTitle().toString());
    } else if (id == R.id.nav_manage) {
        newFragment = FragmentD.newInstance(id, item.getTitle().toString());
    } else if (id == R.id.nav_share) {

    } else if (id == R.id.nav_send) {

    }

    if (newFragment != null) {
        openFragment(newFragment);
    }

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);
    return true;
}

Нагрузи фрагментов

Первый раз, который хочет загрузить фрагмент использовать add так, когда нет больше фрагментов в батарейку, он выйдет из app.

private void addFragment(Fragment newFragment) {

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.add(R.id.frame_container, newFragment);
    ft.commit();

}

Для других фрагментов

private void replaceFragment(Fragment newFragment) {

    FragmentManager fm = getSupportFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    ft.replace(R.id.frame_container, newFragment);
    ft.addToBackStack(newFragment.getClass().getName());
    ft.commit();

}

Предотвращать груз настоящего фрагмента в виде

Если ты идентифицируешь FrameLayout с идентификатором, в этом случае frame_container следующей функцией ты можешь предотвращать удвоение от того, чтобы загружать фрагмент:

private void openFragment(Fragment newFragment){
    if (!containerFragment.getClass().getName().equalsIgnoreCase(newFragment.getClass().getName())) {
        replaceFragment(newFragment);
    }
}

Включать все в функции так груз первого фрагмента и других с предотвращением груза дублированного фрагмента:

private void openFragment(Fragment newFragment) {
    Fragment containerFragment = getSupportFragmentManager().findFragmentById(R.id.frame_container);

    if (containerFragment == null){
        addFragment(newFragment);
    } else{
        if (!containerFragment.getClass().getName().equalsIgnoreCase(newFragment.getClass().getName())) {
            replaceFragment(newFragment);
        }
    }
}

Если после того, как инициализируешь app, ты хочешь загрузить фрагмент в частности:

onNavigationItemSelected(navigationView.getMenu().findItem(R.id.nav_gallery));

Вычислять возврат

Чтобы контролировать действие возврата с Fragments и имея в виду, что есть один NavigationView onBackPressed это быть должный оставаться так

@Override
public void onBackPressed() {

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {

        if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
            getSupportFragmentManager().popBackStack();
        } else {
            super.onBackPressed();
        }

    }
}
1
ответ дан 24.11.2019, 13:09
  • 1
    Хорошая работа, я буду осуществлять это – Luis Rene Mas Mas 11.09.2017, 23:53
  • 2
    спасибо за дружелюбный вклад, добро, объясненное, осуществленное без проблем, привета – Wilmer 05.09.2019, 17:32