Как заменить фрагмент активности из самого фрагмента?
В моем приложении есть фрагмент внутри его действия. Я хотел бы программно заменить фрагмент на другой из самого текущего фрагмента.
Например, если я нажимаю на кнопку внутри фрагмента, фрагмент должен быть заменен другим, но действие должно оставаться тем же.
Возможно ли это? Если да, то как это сделать?
Ответы
Ответ 1
На самом деле легко вызвать операцию для замены фрагмента.
Вам нужно нажать getActivity():
((MyActivity) getActivity())
Затем вы можете вызывать методы из MyActivity, например:
((MyActivity) getActivity()).replaceFragments(Object... params);
Конечно, это предполагает, что у вас есть метод replaceFragments() в вашей деятельности, который обрабатывает процесс замены фрагмента.
Изменить: @ismailarilik добавил возможный код replaceFragments в этом коде с первым комментарием ниже, который был написан @silva96:
Код replaceFragments может быть:
public void replaceFragments(Class fragmentClass) {
Fragment fragment = null;
try {
fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment)
.commit();
}
Ответ 2
из официальных документов:
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
В этом примере newFragment заменяет любой фрагмент (если он есть) в настоящее время в контейнере макета, идентифицированном идентификатором R.id.fragment_container
. Вызывая addToBackStack()
, замененный фрагмент сохраняется в фоновом стеке, поэтому пользователь может отменить транзакцию и вернуть предыдущий фрагмент, нажав кнопку "Назад".
Поведение, которое вы описали, именно то, что предназначены для фрагментов. Пожалуйста, ознакомьтесь с официальным руководством для полного понимания фрагментов, которые помогут вам решить все ваши вопросы.
http://developer.android.com/guide/components/fragments.html
Ответ 3
Обратите внимание, что фрагмент должен НЕ напрямую заменять себя или любые другие фрагменты. Фрагменты должны быть отдельными объектами. Какой фрагмент должен сделать, так это сообщить родительской активности о том, что произошло какое-то событие. Но это опять же НЕ фрагментная работа, чтобы решить, что с этим делать! Это должно быть действием, чтобы принять решение о замене фрагмента на телефоне, но, то есть добавлении другого в существующий на планшетах. Таким образом, вы в основном делаете что-то не так по дизайну.
И, как уже упоминалось ранее, ваша работа должна использовать FragmentManager ( "родной" или из библиотеки совместимости) для выполнения задания (например, replace()
или add()
или remove()
):
http://developer.android.com/guide/components/fragments.html
Ответ 4
Так же, как сказал Марсин, у вас не должно быть фрагмента, начинающегося с другого фрагмента или активности. Лучший способ справиться с этой ситуацией - создать реализацию обратного вызова для основного действия для обработки запросов, таких как запуск нового фрагмента. Здесь - отличный пример в руководстве разработчика Android.
Ответ 5
Есть способ, который работает; Просто (во фрагменте) сделайте следующее:
getFragmentManager().beginTransaction()
.add(R.id. container_of_this_frag, new MyNewFragment())
.remove(this)
.commit();
Ответ 6
При использовании вложенных фрагментов мы не хотим, чтобы каждая внутренняя замена фрагмента уходила во внешнюю большую часть деятельности. Может быть полезен механизм, позволяющий фрагменту уведомлять своего родителя о том, что он хочет перейти на другой фрагмент.
Вот мой код на Kotlin, я думаю, что это легко перевести на Java.
interface FragmentNavigator {
fun navigateTo(fragment: Fragment)
}
class NavigableFragment: Fragment() {
var navigator: FragmentNavigator? = null
override fun onDetach() {
super.onDetach()
navigator = null
}
}
Внутренние фрагменты должны расширять NavigableFragment
и использовать следующий код, чтобы изменить себя на другой фрагмент.
navigator?.navigateTo(anotherFragment)
Внешние действия или фрагменты должны реализовывать FragmentNavigator
и переопределять navigateTo
.
override fun navigateTo(fragment: Fragment) {
supportFragmentManager.beginTransaction().replace(view_id, fragment).commit()
}
//Use childFragmentManager instead of supportFragmentManager a fragment
Наконец, во внешних действиях или фрагментах переопределите onAttachFragment
override fun onAttachFragment(fragment: Fragment?) {
super.onAttachFragment(fragment)
if(fragment is NavigableFragment) {
fragment.navigator = this
}
}