Фрагмент Android покрывается другим фрагментом

#java #android-fragments

#java #android-фрагменты

Вопрос:

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

Вот как я меняю фрагменты:

 WorkoutDetailFragment details = new WorkoutDetailFragment();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
details.setWorkout(id);
ft.replace(R.id.stopwatch_container, details);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
  

Как я могу это предотвратить?

UPD: вот acivity_main.xml файл:

 <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:padding="16dp"
    tools:context=".StopwatchFragment" >

    <fragment
        android:id="@ id/fragment2"
        android:name="com.example.workout.WorkoutListFragment"
        android:layout_width="160dp"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <FrameLayout
        android:id="@ id/stopwatch_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toEndOf="@ id/fragment2"
        app:layout_constraintTop_toTopOf="parent">

        <fragment
            android:id="@ id/fragment3"
            android:name="com.example.workout.WorkoutDetailFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
  

UPD2: я нашел решение. Я просто сохранил представление фрагмента, вложенное в макет фрейма. Вместо этого, используя фрагментные транзакции, я добавил фрагмент непосредственно в макет фрейма в коде.

Комментарии:

1. Пожалуйста, опубликуйте XML-макет activity, который является контейнером.

2. @Rajasekhar В этом уже нет необходимости, я нашел решение. Я просто сохранил представление фрагмента, вложенное в макет фрейма. Вместо этого я добавил фрагмент непосредственно в макет фрейма в коде. Теперь он работает хорошо

3. Рад, что вы это исправили, но посмотрите Мое решение, чтобы понять, как вызвать фрагмент из activity и fragment.

Ответ №1:

Как работает терминология фрагментов:

getSupportFragmentManager()

Это может быть вызвано из Activity или только с использованием ссылки на activity, например requireActivity().getSupportFragmentManager()

  • Это возвращает FragmentManager для взаимодействия с фрагментами, связанными с действием.

getChildFragmentManager()

Если вы находитесь в Activity : вы не можете вызвать это непосредственно из activity или даже использовать requireActivity() , если вы находитесь в Fragment : вы можете вызвать это, потому что для этого требуется, чтобы вы были в fragment. Когда вы находитесь в первом фрагменте, теперь это становится родительским фрагментом. Теперь родительский фрагмент может иметь дочерние фрагменты, но activity не может иметь дочернего frgament. Обычно это видно при использовании ViewPagers или вложенных ViewPager или во вложенных фрагментах.

  • Это возвращает частный FragmentManager для размещения и управления фрагментами внутри этого фрагмента.

Я думаю, нам не нужно об этом писать getParentFragmentManager() .

Тогда позвольте мне начать с контейнера активности.

activity_main

 <FrameLayout
    android:id="@ id/stopwatch_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</FrameLayout>
  

MainActivity

Пожалуйста, добавьте переходы или обратный стек, если это необходимо.

Я звоню getSupportFragmentManager() , потому что мы находимся в активности. Если вызов внутри фрагмента, то отличается.

 WorkoutDetailFragment fragment = new WorkoutDetailFragment();
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.stopwatch_container, fragment);
transaction.commit();
  

Теперь вы пытаетесь вызвать другой фрагмент из WorkoutDetailFragment let’s call HomeFragment

 HomeFragment fragment = new HomeFragment.newInstance();
FragmentManager manager = requireActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.stopwatch_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
  

Чтобы вызвать фрагмент из существующего фрагмента, получите ссылку на родительскую активность requireActivity() и вызовите getSupportFragmentManager() ее.

Комментарии:

1. Спасибо за объяснение. Я не понимаю только одного: чем ваш способ вызова фрагмента из другого отличается от вызова метода getChildFragmentManager(), а затем вызова методов begin — replace — commit ?

2. Хорошо, я понял вас, я добавлю это к своему ответу через минуту.

3. @Alxa я добавил информацию в начало существующего ответа.