私のアプリケーションには、アクティビティ内にフラグメントがあります。プログラムでフラグメントを現在のフラグメント自体の別のフラグメントに置き換えたいと思います。
たとえば、フラグメント内のボタンをクリックすると、フラグメントは別のフラグメントに置き換えられますが、アクティビティは同じままである必要があります。
出来ますか?もしそうなら、それを行う方法は?
私のアプリケーションには、アクティビティ内にフラグメントがあります。プログラムでフラグメントを現在のフラグメント自体の別のフラグメントに置き換えたいと思います。
たとえば、フラグメント内のボタンをクリックすると、フラグメントは別のフラグメントに置き換えられますが、アクティビティは同じままである必要があります。
出来ますか?もしそうなら、それを行う方法は?
公式ドキュメントから:
// 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
IDで識別されるレイアウトコンテナに現在存在するフラグメント(存在する場合)を置き換えます。を呼び出すaddToBackStack()
と、置き換えられたフラグメントがバックスタックに保存されるため、ユーザーはトランザクションを元に戻し、[戻る]ボタンを押して前のフラグメントを戻すことができます。
あなたが説明した振る舞いは、まさにフラグメントが行うように設計されているものです。すべての質問を解決するフラグメントを完全に理解するには、公式ガイドを参照してください。
http://developer.android.com/guide/components/fragments.html
フラグメントを置き換えるためにアクティビティを呼び出すのは実際には簡単です。
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();
}
フラグメントは、それ自体または他のフラグメントを直接置き換えてはならないことに注意してください。フラグメントは個別のエンティティである必要があります。フラグメントが行うべきことは、何らかのイベントが発生したことを親アクティビティに通知することです。しかし、繰り返しになりますが、それをどうするかを決めるのは断片的な仕事ではありません!つまり、電話でフラグメントを置き換えることを決定するが、タブレットで既存のフラグメントに別のフラグメントを追加することを決定するのは活動であるはずです。つまり、基本的には設計上、何か間違ったことをしているのです。
そして、他の人がすでに述べたように、あなたの活動はFragmentManager(「ネイティブ」または互換性ライブラリから)を使用して仕事をする必要があります(またはのようにreplace()
):add()
remove()
http://developer.android.com/guide/components/fragments.html
マーシンが言ったように、フラグメントに別のフラグメントまたはアクティビティを開始させるべきではありません。この状況を処理するためのより良い方法は、新しいフラグメントの開始などの要求を処理するためのメインアクティビティのコールバック実装を作成することです。 これは、Android開発者ガイドの優れた例です。
うまくいく方法があります。(フラグメント内で)次のことを実行します。
getFragmentManager().beginTransaction()
.add(R.id. container_of_this_frag, new MyNewFragment())
.remove(this)
.commit();
ネストされたフラグメントを使用する場合、すべての内部フラグメントの置換が最も外部のアクティビティに行われることは望ましくありません。フラグメントが別のフラグメントに変更したいことを親に通知できるようにするメカニズムが役立つ場合があります。
これが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
}
}
これは私のために働いた:
getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
new MenuFragment()).commit();