[解決済み] BackStackから既存のFragmentをレジュームする方法
質問
フラグメントの使い方を勉強中です。私は、3つのインスタンスの
Fragment
で初期化されているものです。このようなアクティビティにフラグメントを追加しています。
宣言して初期化する。
Fragment A = new AFragment();
Fragment B = new BFragment();
Fragment C = new CFragment();
置き換える/追加する
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, A);
ft.addToBackStack(null);
ft.commit();
これらのスニペットは正しく動作しています。すべてのフラグメントはアクティビティにアタッチされ、問題なくバックスタックに保存されます。
で、起動すると
A
,
C
で、次に
B
の場合、スタックはこのようになります。
| |
|B|
|C|
|A|
___
そして「戻る」ボタンを押すと
B
は破棄され
C
が再開される。
しかし、フラグメントを起動すると
A
二度目は、バックスタックから再開するのではなく、バックスタックの一番上に追加されます。
| |
|A|
|C|
|A|
___
しかし、私は再開したい
A
で、その上にあるすべてのフラグメントを破棄します (ある場合)。実は、私はデフォルトのバックスタック動作が好きなだけなのです。
どうすれば実現できるのでしょうか?
期待すること: (
A
を再開し、トップフラグメントを破棄する必要があります)
| |
| |
| |
|A|
___
編集:(提案者:A--Cさん)
これは私が試したコードです。
private void selectItem(int position) {
Fragment problemSearch = null, problemStatistics = null;
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
String backStateName = null;
Fragment fragmentName = null;
boolean fragmentPopped = false;
switch (position) {
case 0:
fragmentName = profile;
break;
case 1:
fragmentName = submissionStatistics;
break;
case 2:
fragmentName = solvedProblemLevel;
break;
case 3:
fragmentName = latestSubmissions;
break;
case 4:
fragmentName = CPExercise;
break;
case 5:
Bundle bundle = new Bundle();
bundle.putInt("problem_no", problemNo);
problemSearch = new ProblemWebView();
problemSearch.setArguments(bundle);
fragmentName = problemSearch;
break;
case 6:
fragmentName = rankList;
break;
case 7:
fragmentName = liveSubmissions;
break;
case 8:
Bundle bundles = new Bundle();
bundles.putInt("problem_no", problemNo);
problemStatistics = new ProblemStatistics();
problemStatistics.setArguments(bundles);
fragmentName = problemStatistics;
default:
break;
}
backStateName = fragmentName.getClass().getName();
fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped) {
ft.replace(R.id.content_frame, fragmentName);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
// I am using drawer layout
mDrawerList.setItemChecked(position, true);
setTitle(title[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
問題は、起動時に
A
で、次に
B
で、'戻る'を押してください。
B
が削除され
A
が再開され、2回目の「戻る」を押すとアプリが終了するはずです。しかし、空白のウィンドウが表示され、閉じるには3回目の「戻る」を押さなければなりません。
また、起動時に
A
そして
B
では
C
では
B
また...
期待される。
| |
| |
|B|
|A|
___
実際の
| |
|B|
|B|
|A|
___
をオーバーライドする必要があります。
onBackPressed()
それとも、何か見落としているのでしょうか?
解決方法は?
を読むと ドキュメント トランザクション名かcommitで提供されるidに基づいてバックスタックをポップする方法があります。名前 かもしれない というのは、変更される可能性のある番号を追跡する必要がなく、quot; unique back stack entry"のロジックを強化することができるからです。
バックスタックエントリーは、1つの
Fragment
で、バックステート名をフラグメントのクラス名とします。
getClass().getName()
). そして
Fragment
を使用します。
popBackStackImmediate()
メソッドを使用します。もし true を返したら、バックスタックに Fragment のインスタンスが存在することを意味します。そうでない場合は、実際にFragmentの置換ロジックを実行します。
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}
EDIT
問題は、Aを起動し、次にBを起動し、戻るボタンを押すと、Bが表示されることです。 が削除され、Aが再開される。そして、もう一度戻るボタンを押すことで アプリを終了します。しかし、空白のウィンドウが表示され、もう一回押す必要があります。 をクリックすると閉じます。
これは
FragmentTransaction
がバックスタックに追加されるのは、後でフラグメントを上にポップできるようにするためです。これを手っ取り早く解決するには
onBackPressed()
が1つしかない場合、アクティビティを終了させます。
Fragment
@Override
public void onBackPressed(){
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
finish();
}
else {
super.onBackPressed();
}
}
バックスタックエントリーの重複について、フラグメントがポップされていない場合に置き換えるという条件文は、明らかに 異なる 私の元のコードスニペットのものよりも。あなたがやっていることは、バックスタックがポップされたかどうかに関係なく、バックスタックに追加しているのです。
このようなものが、あなたの望むものに近いはずです。
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
String fragmentTag = backStateName;
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(fragmentTag) == null){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment, fragmentTag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
}
}
表示されている状態で同じフラグメントを選択すると、エントリーの重複も発生するため、条件を少し変更しました。
実装しています。
私は、更新された
replaceFragment()
メソッドを分解してください。すべてのロジックはこのメソッドに含まれており、パーツを動かすと問題が発生する可能性があります。
つまり、更新された
replaceFragment()
メソッドを自分のクラスに追加し
backStateName = fragmentName.getClass().getName();
fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped) {
ft.replace(R.id.content_frame, fragmentName);
}
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
ということで、単純に
replaceFragment (fragmentName);
EDIT #2
バックスタックが変更されたときにドロワーを更新するには、Fragmentを受け取ってクラス名を比較するメソッドを作ります。一致するものがあれば、タイトルと選択範囲を変更する。また
OnBackStackChangedListener
で、有効なFragmentがあれば、updateメソッドを呼び出すようにします。
例えば、Activityの
onCreate()
を追加します。
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
Fragment f = getSupportFragmentManager().findFragmentById(R.id.content_frame);
if (f != null){
updateTitleAndDrawer (f);
}
}
});
そしてもう一つの方法。
private void updateTitleAndDrawer (Fragment fragment){
String fragClassName = fragment.getClass().getName();
if (fragClassName.equals(A.class.getName())){
setTitle ("A");
//set selected item position, etc
}
else if (fragClassName.equals(B.class.getName())){
setTitle ("B");
//set selected item position, etc
}
else if (fragClassName.equals(C.class.getName())){
setTitle ("C");
//set selected item position, etc
}
}
これで、バックスタックが変更されるたびに、タイトルとチェック位置が可視化されます。
Fragment
.
関連
-
問題 ---- Android ---- ActivityManager: Error: アクティビティクラス{xx/xx.MainActivity}が存在しない
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] FragmentでonActivityResultが呼び出されない
-
[解決済み] フラグメントのインスタンス状態をバックスタックに正しく保存する方法は?
-
[解決済み] ViewPagerとフラグメント - フラグメントの状態を保存する正しい方法は何ですか?
-
[解決済み] FragmentのsetRetainInstance(boolean)を理解する。
-
[解決済み] バックスタックに追加されたフラグメントの状態を維持するにはどうすればよいですか?
-
[解決済み] フラグメント・イン・フラグメント
-
[解決済み】フラグメント onResume() & onPause() がバックスタックで呼ばれない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ジャークとして。起動アクティビティを特定できませんでした。デフォルトのアクティビティが見つかりません アクティビティ起動中のエラー
-
を作ってください。*** makeするルールがない エラーの原因、分析、解決策
-
エラーが発生しました。ArrayAdapter は、リソース ID が TextView である必要があります。
-
アンドロイドスタジオのエラーを解決する --> Error:(1, 0) id 'com.android.application' を持つプラグインが見つかりません。
-
Android ProgressBarの色を変更する
-
Android基本アプレット
-
Androidのカラーグラデーション実装のまとめ
-
アプリの実行エラー。ターゲットデバイスが見つからない問題
-
Android.support.v7.widget.Toolbar が見つかりませんでした。
-
Android TextViewは、テキスト内容が表示省略記号を超えているかどうかを判断する