Замена фрагмента другим фрагментом внутри группы действий

У меня есть фрагмент внутри группового действия, и я хочу заменить его другим фрагментом:

FragmentTransaction ft = getActivity().getFragmentManager().beginTransaction();
SectionDescriptionFragment bdf = new SectionDescriptionFragment();
ft.replace(R.id.book_description_fragment, bdf);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();

Он отлично работает, когда он выполняется как отдельный проект без использования группы действий, все работает отлично в журнале cat, поскольку управление идет внутри getview (), но не видно никакого представления, даже не возникает никаких исключений, я хочу, чтобы фрагмент детали книги был заменить на фрагмент детали сечения.

XML фрагмента описания книги имеет идентификатор book_description_fragment, а XML фрагмента описания раздела имеет идентификатор section_description_fragment.

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


person Lion Heart    schedule 14.04.2011    source источник


Ответы (12)


Фрагменты, жестко закодированные в XML, не могут быть заменены. Если вам нужно заменить фрагмент другим, вы должны были добавить их в первую очередь динамически.

Примечание. R.id.fragment_container - это макет или контейнер по вашему выбору в действии, в которое вы переносите фрагмент.

// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);

// Commit the transaction
transaction.commit();
person Subin Sebastian    schedule 22.09.2013
comment
что такое R.id.fragment_container в этом случае? - person Guy; 17.07.2014
comment
@Guy, это может быть любой макет, в который вы хотите загрузить фрагмент. - person Subin Sebastian; 18.07.2014
comment
Могу ли я пропустить addToBackStack, если мне не нужно поведение кнопки «Назад» для определенного фрагмента? - person Divyansh Goenka; 10.04.2015
comment
каким должно быть имя фрагмента в xml файле? Я хочу добавить фрагмент динамически и не хочу статического фрагмента. - person Rajat Mehra; 30.06.2015
comment
@RajatMehra Если вы хотите добавлять фрагменты динамически, вам вообще не нужно указывать фрагмент внутри XML. Вы можете использовать представление контейнера. Пожалуйста, прочтите ответ еще раз. - person Subin Sebastian; 02.07.2015
comment
Фрагменты, жестко закодированные в XML, заменить нельзя. - Я согласен с Джомией: это информация, которую я не мог найти в другом месте, когда пытался выяснить, почему мой макет не был заменен. Спасибо за это! - person zreptil; 31.08.2015
comment
Если имя этого фрагмента зафиксировано в файле xml, это не сработает. - person LKM; 12.10.2015
comment
Почему в документах Android нет такой информации и людям приходится работать над этим методом проб и ошибок? - person Ahmed; 20.12.2015
comment
@Ahmed Причина в том, что по архитектуре система заменяет каждый тег ‹fragment› представлением (группой), предоставленным соответствующими фрагментами onCreateView(). Таким образом, как вы можете предположить, любая ссылка на фрагмент фактически теряется на уровне представления. Таким образом, вы в принципе не можете заменить фрагмент, но вы можете вручную удалить представления, которые теперь присутствуют в контейнере, и вместо этого поместить фрагмент, если это необходимо. - person Subin Sebastian; 21.12.2015
comment
fragment_container может быть ограничивающим макетом оригинала? - person luke cross; 30.04.2020

См. Этот вопрос

Вы можете заменить только «динамически добавляемый фрагмент».

Итак, если вы хотите добавить динамический фрагмент, см. этот пример.

person Sana    schedule 05.06.2011
comment
Привет . Я нашел решение, на самом деле я не помещал содержимое фрагмента в макет, вместо этого я использовал другой фрагмент для содержимого предыдущего фрагмента - person Lion Heart; 06.06.2011
comment
Нет, здесь я искал заменить весь фрагмент новым фрагментом. - person Sana; 07.06.2011
comment
@Lion Heart, не могли бы вы уточнить решение, которое вы нашли? - person Namratha; 22.01.2013
comment
Ссылка мертвая: / - person Neon Warge; 27.07.2016

Я воспользовался идеальным методом для управления заменой фрагмента и жизненным циклом.

Он только заменяет текущий фрагмент новым, если он не тот, и если он не находится в backstack (в этом случае он вытолкнет его).

В нем есть несколько вариантов, как если бы вы хотели, чтобы фрагмент был сохранен в backstack.

=> См. Gist здесь

Используя это и одно действие, вы можете добавить это в свое действие:

@Override
public void onBackPressed() {
    int fragments = getSupportFragmentManager().getBackStackEntryCount();
    if (fragments == 1) {
            finish();
            return;
    }

    super.onBackPressed();
}
person Hugo Gresse    schedule 02.03.2016
comment
@ RémiP ссылка работает должным образом. Вы можете проверить тот, который может быть лучше IMO github.com/HugoGresse/Anecdote/blob/master/app/src/main/java/io/. - person Hugo Gresse; 28.07.2017

Используйте приведенный ниже код в android.support.v4

FragmentTransaction ft1 = getFragmentManager().beginTransaction();
WebViewFragment w1 = new WebViewFragment();
w1.init(linkData.getLink());
ft1.addToBackStack(linkData.getName());
ft1.replace(R.id.listFragment, w1);
ft1.commit();
person Sachin Suthar    schedule 28.09.2016

Используйте этот код, используя v4

 ExampleFragment newFragment = new ExampleFragment();     
 FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();  
 // Replace whatever is in the fragment_container view with this fragment,  
 // and add the transaction to the back stack so the user can navigate back   
 transaction.replace(R.id.container, newFragment);
 transaction.addToBackStack(null);  
 // Commit the transaction   
 transaction.commit();
person Manish Butola    schedule 03.10.2016

Используйте ViewPager. Для меня это работа.

final ViewPager viewPager = (ViewPager) getActivity().findViewById(R.id.vp_pager); 
button = (Button)result.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        viewPager.setCurrentItem(1);
    }
});
person Nikolay    schedule 09.01.2018

Надеюсь, у вас все хорошо. Когда я начал работать с Android Fragments, у меня тоже была такая же проблема, тогда я прочитал о 1- Как переключить фрагмент с другим. 2- Как добавить фрагмент, если Fragment container не имеет фрагмента.

затем, после некоторых исследований и разработок, я создал функцию, которая до сих пор помогает мне во многих проектах, и я все еще использую эту простую функцию.

public void switchFragment(BaseFragment baseFragment) {
    try {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
        if (getSupportFragmentManager().findFragmentById(R.id.home_frame) == null) {
            ft.add(R.id.home_frame, baseFragment);
        } else {
            ft.replace(R.id.home_frame, baseFragment);
        }
        ft.addToBackStack(null);
        ft.commit();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

наслаждайся своим кодом :)

person John smith    schedule 07.02.2017
comment
Почему вам нужно обернуть код транзакции фрагмента внутри try catch с общим исключением? - person Banana droid; 08.09.2020

Вы можете использовать этот код

((AppCompatActivity) getActivity()).getSupportFragmentManager().beginTransaction().replace(R.id.YourFrameLayout, new YourFragment()).commit();

или вы можете использовать этот код

YourFragment fragments=(YourFragment) getSupportFragmentManager().findFragmentById(R.id.FrameLayout);

        if (fragments==null) {
            getSupportFragmentManager().beginTransaction().replace(R.id.FrameLayout, new Fragment_News()).commit();
        }
person Diako Hasani    schedule 31.07.2019

Я изменяю фрагмент динамически в однострочном коде
Это работает в любой версии SDK и androidx
Я использую навигацию как BottomNavigationView

    BottomNavigationView btn_nav;
    FragmentFirst fragmentFirst;
    FragmentSecond fragmentSecond;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        fragmentFirst = new FragmentFirst();
        fragmentSecond = new FragmentSecond ();
        changeFragment(fragmentFirst); // at first time load the fragmentFirst
        btn_nav = findViewById(R.id.bottomNav);
        btn_nav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                switch(menuItem.getItemId()){
                    case R.id.menu_first_frag:
                        changeFragment(fragmentFirst); // change fragmentFirst
                        break;
                    case R.id.menu_second_frag:
                        changeFragment(fragmentSecond); // change fragmentSecond
                        break;
                        default:
                            Toast.makeText(SearchActivity.this, "Click on wrong bottom SORRY!", Toast.LENGTH_SHORT).show();
                }
                return true;
            }
        });
    }
public void changeFragment(Fragment fragment) {
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_layout_changer, fragment).commit();
    }
person Mahdi Safari    schedule 07.12.2019

В котлине вы можете:

// instantiate the new fragment
val fragment: Fragment = ExampleFragment()

val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.book_description_fragment, fragment)
transaction.addToBackStack("transaction_name")
// Commit the transaction
transaction.commit()
person Nicola Gallazzi    schedule 15.02.2019

вы можете использовать простой код для его работы для транзакции

Fragment newFragment = new MainCategoryFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame_NavButtom, newFragment);
ft.commit(); 
person Community    schedule 21.09.2018

Это сработает, если вы пытаетесь заменить фрагмент другим фрагментом.

Objects.requireNonNull(getActivity()).getSupportFragmentManager()
.beginTransaction()
.replace(R.id.home_fragment_container,new NewFragment())

ПРИМЕЧАНИЕ. Как указано в ответах выше, вам нужны динамические фрагменты.

person emkarachchi    schedule 11.08.2020