Фрагмент над другим фрагментом, появляющимся после выхода из фона

#android #android-fragments

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

Вопрос:

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

 public class HomeActivity extends AppCompatActivity {

private final Fragment fragment1 = new Fragment1();
private final Fragment fragment2 = new Fragment2();
private final Fragment fragment3 = new Fragment3();
private final FragmentManager fm = getSupportFragmentManager();

private Fragment active = fragment1;

private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
        = item -> {
            switch (item.getItemId()) {
                case R.id.navigation_home:
                    fm.beginTransaction().hide(active).show(fragment1).commit();
                    active = fragment1;
                    return true;
                case R.id.navigation_dashboard:
                    fm.beginTransaction().hide(active).show(fragment2).commit();
                    active = fragment2;
                    return true;
                case R.id.navigation_notifications:
                    fm.beginTransaction().hide(active).show(fragment3).commit();
                    active = fragment3;
                    return true;
            }
            return false;
        };


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_screen);

    //Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this));

    BottomNavigationView navigation = findViewById(R.id.navigation);
    navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
    fm.beginTransaction().add(R.id.container, fragment3, "3").hide(fragment3).commit();
    fm.beginTransaction().add(R.id.container, fragment2, "2").hide(fragment2).commit();
    fm.beginTransaction().add(R.id.container, fragment1, "1").commit();

}
  

}

Как это решить? Любая помощь

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

1. Вместо того, чтобы использовать hide , вы должны использовать replace в транзакции фрагмента

2. replace уничтожит фрагмент, и его воссоздание — это обширная работа для нас, поскольку будет несколько вызовов API

Ответ №1:

Вы можете добавлять только один фрагмент одновременно после того, как по щелчку нижней навигации замените только фрагмент и в вашем XML-файле не добавляйте класс фрагмента.

 private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
            = item -> {
                switch (item.getItemId()) {
                    case R.id.navigation_home:
                       setFragment(new fragment1());

                        return true;
                    case R.id.navigation_dashboard:
                        setFragment(new fragment2());

                        return true;
                    case R.id.navigation_notifications:
                       setFragment(new fragment3());

                        return true;
                }
                return false;
            };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen);


        BottomNavigationView navigation = findViewById(R.id.navigation);
        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

  FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = 
                    fragmentManager.beginTransaction();
                fragmentTransaction.add(android.R.id.content, fragment1);
                fragmentTransaction.commit();


    }

    protected void setFragment(Fragment fragment) {
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = 
                    fragmentManager.beginTransaction();
                fragmentTransaction.replace(android.R.id.content, fragment);
                fragmentTransaction.commit();


       }
  

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

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

2. если вы хотите обновить данные во втором фрагменте, вы можете использовать метод onFragmentVisible. который вызывается каждый раз, когда фрагмент виден пользователю.

Ответ №2:

Попробуйте этот способ

создайте представление для транзакции фрагмента

 <FrameLayout
   .....
    android:layout_above="@ id/navigation"
   ....
    app:layout_behavior="@string/appbar_scrolling_view_behavior" />
 <android.support.design.widget.BottomNavigationView/>
  

и в вашем классе замените макет фрейма на фрагмент
используя

  private boolean loadFragment(Fragment fragment) {
    if(fragment!=null ) {
        getSupportFragmentManager().beginTransaction()
        .addToBackStack(null)
        .replace(R.id.frame_container, fragment)
        .commit();
        return true;
    }
    return false;

}
  

Ответ №3:

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

1) Сохранение экземпляров фрагмента.

Поскольку экземпляры могут быть уничтожены и воссозданы заново, вместо того, чтобы хранить экземпляры фрагмента ( fragment1 , fragment1 , fragment3 ), просто сохраните ссылку на строку тега фрагмента. В том виде, в каком он у вас есть сейчас, фрагмент на экране может отличаться от экземпляра, который вы удерживаете в activity, который фактически должен был быть собран из мусора. (утечка памяти)

Когда вам нужно что-то сделать с фрагментом, используйте SupportFragmentManager.findFragmentByTag(theGragmentTag);

2) Создание фрагмента в onCreate действия

В activity onCreate(savedBundle) создавайте, fragments только когда savedBundle значение равно null. В противном случае фрагменты начнут дублироваться и, скорее всего, будут показывать поведение, которое вы описываете, один поверх другого.

3) Фрагменты могут быть уничтожены в фоновом режиме

Предположим, что фрагмент может быть уничтожен, когда его нет на экране, поэтому сохраните и восстановите необходимую вам информацию. Сохраните в onPause() , восстановите в зависимости от ваших потребностей: onResume() , setUserVisibleHint(boolean)

Примечание: Если пользовательский интерфейс должен обновляться, когда фрагмент становится видимым, onResume() alone не будет выполнять эту работу, потому что он, возможно, уже был вызван, когда его соседний фрагмент стал видимым. В этой ситуации вам нужно будет объединить onResume() с setUserVisibleHint(true) , чтобы согласовать, когда обновлять пользовательский интерфейс.