Фрагмент с множественным обратным стеком - PullRequest
10 голосов
/ 07 марта 2012

Насколько я понимаю, каждый фрагмент имеет свой собственный backstack, и он разделяется со всеми фрагментами, которые принадлежат FragmentActivity. Предположим, вам нужно управлять несколькими вкладками, и каждая вкладка может перемещаться по нескольким фрагментам. Предположим, вы хотите «записать» историю навигации для каждой вкладки, поэтому переключение между фрагментами позволит вам вернуться к фрагменту, который вы просматривали. Возможно ли достичь? Нужно ли связывать каждую вкладку с действием фрагмента? В этом случае как можно переключаться между FragmentActivity?

Ответы [ 3 ]

7 голосов
/ 13 января 2013

Не существует «стандартного» способа добиться этого, потому что этот стиль дизайна не рекомендуется. Однако я нашел способ заставить его работать: вы создадите навигацию вручную.

Ваше приложение должно иметь одно действие - FragmentActivity. Он имеет FragmentTabHost, который будет содержать каждый из ваших фрагментов TabFragment.

TabFragment - это абстрактный класс, который я создал для представления вашей вкладки в TabSpec. Он будет управлять навигацией и заменой фрагментов на вкладке.

Затем отдельные созданные вами фрагменты можно поменять местами внутри объекта TabFragment. Вот код:

Активность

    public class MainActivity extends FragmentActivity {

            private FragmentTabHost tabHost;

//(TabFragment)s will set this property when created so the Activity can communicate with it
            public TabFragment activeFragment;

            @Override
            public void onCreate(Bundle savedInstanceState){
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);

        //create tabHost based on .xml layout
                tabHost = (FragmentTabHost)findViewById(R.id.tabhost);
                tabHost.setup(this, getSupportFragmentManager(), R.id.tabcontent);

        //add each of your tabs to the tabHost. These are all (TabFragment)s
                tabHost.addTab(tabHost.newTabSpec("New Tab").setIndicator("New Tab"),
                      ExampleTabFragment.class, null);
            }

    /*override the onBackPressed method, so that your application does not close every 
time the user navigates back. Instead, calls the activeFragment to determine behavior*/
            @Override
            public void onBackPressed() {
                activeFragment.onBackPressed();
            }

    //method for TabFragment to call when the user navigates out of the app
            public void close(){
                super.onBackPressed();
            }
        }

TabFragment

    public abstract class TabFragment extends Fragment {

        @Override
        public void onResume(){

//sets the property in the Activity so we can reference this from it.
            ((MainActivity) getActivity()).activeFragment=this;
            super.onResume();
        }

//this will be the method called when the back button is pressed. It will navigate.
        public abstract void onBackPressed();

    }

Экземпляр TabFragment Внутри экземпляра TabFragment должен быть FrameLayout, к которому могут быть прикреплены дочерние фрагменты. При первом нажатии на вкладку запускается фрагмент, указанный в onCreate(). После переключения на него из другой вкладки, он возобновит любой фрагмент, который отображался в последний раз. Метод onBackPressed () должен использоваться для перехода назад по фрагментам, если требуется иерархическая навигация. Я использовал свойство байта (tabContentIndex), чтобы определить, как перемещаться. Фрагменты могут поменяться местами для других фрагментов, если вы добавите конструктор, который принимает и экземпляр этого TabFragment. Они будут делать это, используя методы start(Example)Fragment(). Помните, что кнопка «Назад» должна в конечном итоге выйти из приложения.

public class NewTrailTabContent extends TabFragment {

    //to determine what child Fragment is active
    byte tabContentIndex;

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

//a simple FrameLayout in this case. Child Fragments will be attached.
        return inflater.inflate(R.layout.example_fragment, container,
                false);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {

//The tab starts with this Fragment
        startDiologFragment();
        super.onCreate(savedInstanceState);
    }

    public void startExampleFragment(){

/*Fragment's constructor allows us to reference the parent to navigate. In effect, this 
Fragment will be able to call these navigation methods.*/
        ExampleFragment newFragment = new ExampleFragment(this);
        FragmentManager fragmentManager = getChildFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();

//this Resource is the FrameLayout
        fragmentTransaction.replace(R.id.example_contentpane,
                newFragment);
        fragmentTransaction.commit();

//this is set so the onBackPressed() method knows how to operate.
        tabContentIndex =0;
    }

    public void startTestFragment(){

        Fragment testFragment = new TestFragment(this);
        FragmentManager fragmentManager = getChildFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();
        fragmentTransaction.replace(R.id.example_contentpane,
                testFragment);
        fragmentTransaction.commit();

//different contentIndex
        tabContentIndex = 1;
    }

//this method called by the Activity
    @Override 
    public void onBackPressed() {

//this will close the app because we are at the top of the hierarchy
        if(tabContentIndex==0){
            ((MainActivity)getActivity()).close();

//this will switch to the original content fragment.
        }else if(tabContentIndex==1||tabContentIndex==2){
            startExampleFragment();
        }
    }
}
1 голос
/ 18 февраля 2016

FragmentTransaction имеет метод addToBackStack () .

Открыть новый фрагмент этот путь:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
transaction.commit();

Используя этот метод, когда пользователь нажимает кнопку «Назад», он показывает предыдущий фрагмент текущей вкладки, а когда стек фрагментов очищается от текущей вкладки, он выходит из приложения.

Метод addToBackStack () добавляет эту транзакцию в задний стек. Это означает, что транзакция будет запомнена после того, как она будет зафиксирована, и обратится к своей операции, когда позднее будет извлечена из стека.

1 голос
/ 12 июля 2012

Это не очень хороший способ навигации.Я бы порекомендовал вам.Посмотрите на шаблоны Android Design и подумайте о своем потоке.

Но да, без написания собственного FragmentManager вам понадобится несколько FragmentActivities

Посмотрите на использование TaskStacks Но это действительно работает только на HoneyComb.Поэтому я бы порекомендовал переосмыслить вашу навигацию ИЛИ только построить приложение HC +.

Я знаю, что я не даю вам много кода, чтобы действительно решить вашу проблему.Но хорошо читайте Android-навигация Она объясняет временную и наследственную навигацию, которая была «официально» добавлена ​​с Android 3.0 +

...