- Андроид — фрагмент.replace() не заменяет содержимое — помещает его сверху
- 12 ответов:
- Fragment transactions
- Kotlin
- Kotlin
- Allow reordering of fragment state changes
- Kotlin
- Adding and removing fragments
- Kotlin
- Commit is asynchronous
- Operation ordering is significant
- Kotlin
- Limit the fragment’s lifecycle
- Showing and hiding fragment’s views
- Attaching and detaching fragments
Андроид — фрагмент.replace() не заменяет содержимое — помещает его сверху
проблема в том, что контент на самом деле не заменяется — он помещается сверху (поэтому он перекрывается).
когда я нажимаю назад, первый фрагмент отображается правильно (без второго), но изначально оба видны (я хочу, чтобы был виден только последний).
что мне здесь не хватает?
12 ответов:
Вы делаете две вещи неправильно здесь:
вы не можете заменить фрагмент, который статически помещается в макет. Вы должны создать контейнер (например, FrameLayout ) в макете, а затем добавить фрагмент программно с помощью FragmentTransaction .
FragmentTransaction.replace ожидает идентификатор контейнера, который содержит фрагмент, а не идентификатор фрагмента в качестве первого параметра. Поэтому вы должны передать первый аргумент как идентификатор контейнера, в который вы добавили первый фрагмент.
вы можете обратиться к этой ссылке для более подробной информации.
У меня была аналогичная проблема, но моя проблема заключалась в том, что я использовал два разных менеджера фрагментов: Один из getSupportFragmentManager () и один из getFragmentManager (). Если я добавил один фрагмент с SupportFragmentManager, а затем попытался заменить фрагмент на FragmentManager, фрагмент просто добавится сверху. Мне нужно было изменить код, чтобы использовать тот же FragmentManager, и это решило проблему.
сайт разработчика android предлагает использовать FrameLayout для динамической загрузки фрагментов во время выполнения. Вы жестко закодировали фрагмент в своем xml-файле. Поэтому он не может быть удален во время выполнения, как указано в этой ссылке:
эта ссылка показывает, как добавить фрагменты через программа:
у меня была та же проблема, и я видел все ответы, но ни один из них не содержал моей ошибки! Прежде чем пытаться заменить текущий фрагмент, я показывал фрагмент по умолчанию в xml действия контейнера следующим образом:
после этого, хотя я проходил мимо FrameLayout до fragmentTransaction.replace() но у меня была такая же проблема. он показывал второй фрагмент поверх предыдущего.
проблема устранена путем удаления фрагмента из xml и показывая его программно в onCreate() метод действия контейнера для предварительного просмотра по умолчанию при запуске программы следующим образом:
и активность контейнера xml:
вы можете очистить backStack перед заменой фрагментов:
я согласен с ответом Сапана Дивакара. Но я нашел обходной путь, как это сделать.
во-первых, в вашей деятельности(например, activity_main ), где у вас есть все макеты, добавьте FrameLayout . Это высота и ширина должны быть match parent . Кроме того, дайте ему id .
теперь, в вашем фрагменте, который собирается заменить текущий макет, позвоните onPause() и onResume() . Инициализируйте все внутренние контейнеры в View . И установить их visibility to GONE на onResume() и VISIBLE на onPause() .
Примечание: нет FrameLayout который вы заменяете этим фрагментом.
предположим, что у вас есть ViewPager , TabLayout , ImageView и обычай на activity_main.xml . Добавить, а FrameLayout Как уже упоминалось выше.
In abcFragment.java , в добавьте addToBackstack(null) на transaction .
пример кода:
в xyzFragment, который собирается заменить abcFragment (и все, что показано в activity_main.xml), сделайте это
удачи в кодировании!
спасибо Сапану Дивакару и другим. Этот ответ помог мне. Я просто создал RelativeLayout без фрагмента внутри него, использовал RelativeLayout в качестве родительского или группового представления, указал это групповое представление в транзакции для замены, и это сработало.
код: getSupportFragmentManager ().beginTransaction() . replace (R. id.content_group_view, itemDetailFragment).commit ();
используйте контейнер вместо использования фрагмента
теперь в MainActivity
обратите внимание, что ваш класс фрагментов должен импортировать ‘android.приложение.Фрагмент’ Убедитесь, что вы используете «поддержку».v4 » или «оригинальные» реализации и не смешивать их. Я получал эту проблему, потому что я смешал их.
вы можете использовать метод setTransition из FragmentTransaction для устранения проблемы перекрытия.
теперь это всегда будет ваш фрагмент по умолчанию . если вы добавляете фрагмент в XML-макет, он всегда будет перекрываться , поэтому установите начальное содержимое с фрагментом во время выполнения
у меня была такая же проблема после использования эта проблема решена
возьмите макет кадра, где u заменяют фрагмент ur
и код для замены
Если вы хотите весь пример я вышлю вам просто комментировать меня.
у меня также была та же проблема, но это было потому, что я не изменил цвет фона фрагмента, который я пытался добавить в свой framelayout.
попробуйте сделать это с layout_height и layout_width значение match_parent
Источник
Fragment transactions
At runtime, a FragmentManager can add, remove, replace, and perform other actions with fragments in response to user interaction. Each set of fragment changes that you commit is called a transaction, and you can specify what to do inside the transaction using the APIs provided by the FragmentTransaction class. You can group multiple actions into a single transaction—for example, a transaction can add or replace multiple fragments. This grouping can be useful for when you have multiple sibling fragments displayed on the same screen, such as with split views.
You can save each transaction to a back stack managed by the FragmentManager , allowing the user to navigate backward through the fragment changes—similar to navigating backward through activities.
You can get an instance of FragmentTransaction from the FragmentManager by calling beginTransaction() , as shown in the following example:
Kotlin
The final call on each FragmentTransaction must commit the transaction. The commit() call signals to the FragmentManager that all operations have been added to the transaction.
Kotlin
Allow reordering of fragment state changes
Each FragmentTransaction should use setReorderingAllowed(true) :
Kotlin
For behavior compatibility, the reordering flag is not enabled by default. It is required, however, to allow FragmentManager to properly execute your FragmentTransaction , particularly when it operates on the back stack and runs animations and transitions. Enabling the flag ensures that if multiple transactions are executed together, any intermediate fragments (i.e. ones that are added and then immediately replaced) do not go through lifecycle changes or have their animations or transitions executed. Note that this flag affects both the initial execution of the transaction and reversing the transaction with popBackStack() .
Adding and removing fragments
To add a fragment to a FragmentManager , call add() on the transaction. This method receives the ID of the container for the fragment, as well as the class name of the fragment you wish to add. The added fragment is moved to the RESUMED state. It is strongly recommended that the container is a FragmentContainerView that is part of the view hierarchy.
To remove a fragment from the host, call remove() , passing in a fragment instance that was retrieved from the fragment manager through findFragmentById() or findFragmentByTag() . If the fragment’s view was previously added to a container, the view is removed from the container at this point. The removed fragment is moved to the DESTROYED state.
Use replace() to replace an existing fragment in a container with an instance of a new fragment class that you provide. Calling replace() is equivalent to calling remove() with a fragment in a container and adding a new fragment to that same container.
The following code snippet shows how you can replace one fragment with another:
Kotlin
In this example, a new instance of ExampleFragment replaces the fragment, if any, that is currently in the layout container identified by R.id.fragment_container .
By default, the changes made in a FragmentTransaction are not added to the back stack. To save those changes, you can call addToBackStack() on the FragmentTransaction . For more information, see Fragment manager.
Commit is asynchronous
Calling commit() doesn’t perform the transaction immediately. Rather, the transaction is scheduled to run on the main UI thread as soon as it is able to do so. If necessary, however, you can call commitNow() to run the fragment transaction on your UI thread immediately.
Note that commitNow is incompatible with addToBackStack . Alternatively, you can execute all pending FragmentTransactions submitted by commit() calls that have not yet run by calling executePendingTransactions() . This approach is compatible with addToBackStack .
For the vast majority of use cases, commit() is all you need.
Operation ordering is significant
The order in which you perform operations within a FragmentTransaction is significant, particularly when using setCustomAnimations() . This method applies the given animations to all fragment operations that follow it.
Kotlin
Limit the fragment’s lifecycle
FragmentTransactions can affect the lifecycle state of individual fragments added within the scope of the transaction. When creating a FragmentTransaction , setMaxLifecycle() sets a maximum state for the given fragment. For example, ViewPager2 uses setMaxLifecycle() to limit the off-screen fragments to the STARTED state.
Showing and hiding fragment’s views
Use the FragmentTransaction methods show() and hide() to show and hide the view of fragments that have been added to a container. These methods set the visibility of the fragment’s views without affecting the lifecycle of the fragment.
While you don’t need to use a fragment transaction to toggle the visibility of the views within a fragment, these methods are useful for cases where you want changes to the visibility state to be associated with transactions on the back stack.
Attaching and detaching fragments
The FragmentTransaction method detach() detaches the fragment from the UI, destroying its view hierarchy. The fragment remains in the same state ( STOPPED ) as when it is put on the back stack. This means that the fragment was removed from the UI but is still managed by the fragment manager.
The attach() method reattaches a fragment from which it was previously detached. This causes its view hierarchy to be recreated, attached to the UI, and displayed.
As a FragmentTransaction is treated as a single atomic set of operations, calls to both detach and attach on the same fragment instance in the same transaction effectively cancel each other out, thus avoiding the destruction and immediate recreation of the fragment’s UI. Use separate transactions, separated by executePendingOperations() if using commit() , if you want to detach and then immediately re-attach a fragment.
Content and code samples on this page are subject to the licenses described in the Content License. Java is a registered trademark of Oracle and/or its affiliates.
Источник