アクティビティ内に複数のフラグメントがあります。ボタンをクリックして、新しいフラグメントを開始し、バックスタックに追加します。私は当然、現在のフラグメントのonPause()
メソッドと新しいフラグメントのonResume()
メソッドが呼び出されることを期待していました。まあそれは起こっていません。
public class LoginFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
final FragmentManager mFragmentmanager = getFragmentManager();
Button btnHome = (Button)view.findViewById(R.id.home_btn);
btnHome.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
HomeFragment fragment = new HomeFragment();
FragmentTransaction ft2 = mFragmentmanager.beginTransaction();
ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left
, R.anim.slide_left, R.anim.slide_out_right);
ft2.replace(R.id.middle_fragment, fragment);
ft2.addToBackStack("");
ft2.commit();
}
});
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of LoginFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of loginFragment");
super.onPause();
}
}
public class HomeFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of HomeFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of HomeFragment");
super.onPause();
}
}
期待していたのは、
onPause()
ofLoginFragmentに置き換えられます、およびHomeFragmentのonResume()
が呼び出されますonPause()
ofHomeFragmentLoginFragmentのonResume()
が呼び出されます。私が得ているのは、
これは通常の動作ですか? LoginFragmentのonResume()
が戻るボタンを押しても呼び出されないのはなぜですか。
フラグメントonResume()
またはonPause()
は、Activities onResume()
またはonPause()
が呼び出されたときにのみ呼び出されます。それらはActivity
と密接に関係しています。
この記事の「フラグメントのライフサイクル」セクションの処理 を読んでください。
ft2.replace()
を使用したので、FragmentTransaction.remove()
メソッドが呼び出され、Loginfragment
は削除されます。 this を参照してください。そのためonStop()
の代わりにLoginFragment
のonPause()
が呼び出されます。 (新しいフラグメントが古いものを完全に置き換えるので)。ft2.addtobackstack()
も使っているので、Loginfragment
の状態はバンドルとして保存され、HomeFragment
から戻るボタンをクリックするとonViewStateRestored()
が呼び出され、LoginFragment
のonStart()
が呼び出されます。そのため、最終的にonResume()
は呼び出されません。これが私のより堅牢なバージョンのGorの答えです(fragment.size()を使うことはフラグメントがポップされた後にサイズが減らされないため信頼できません)。
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getFragmentManager() != null) {
Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager());
if (topFrag != null) {
if (topFrag instanceof YourFragment) {
//This fragment is being shown.
} else {
//Navigating away from this fragment.
}
}
}
}
});
そして 'getCurrentTopFragment'メソッド:
public static Fragment getCurrentTopFragment(FragmentManager fm) {
int stackCount = fm.getBackStackEntryCount();
if (stackCount > 0) {
FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1);
return fm.findFragmentByTag(backEntry.getName());
} else {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size()>0) {
for (Fragment f: fragments) {
if (f != null && !f.isHidden()) {
return f;
}
}
}
}
return null;
}
本当に他のフラグメントの中にあるフラグメントを置き換えたい場合は、 Nested Fragments を使うべきです。
あなたのコードではあなたが置き換える必要があります
final FragmentManager mFragmentmanager = getFragmentManager();
と
final FragmentManager mFragmentmanager = getChildFragmentManager();
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
List<Fragment> fragments = getFragmentManager().getFragments();
if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){
//todo if fragment visible
} else {
//todo if fragment invisible
}
}
});
ただし、複数のフラグメントが表示されている場合は注意してください。
私はあなたのものと非常によく似たコードを持っていて、それがonPause()とonResume()で動くのであれば。フラグメントを変更すると、これらの機能はそれぞれ有効になります。
フラグメントのコード:
@Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL);
Log.e("Frontales","resume");
}
@Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
Log.e("Frontales","Pause");
}
フラグメントの変更時にログに記録します。
05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause
OnCreateViewをフラグメント化します。
View rootView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_proximidad, container, false);
ButterKnife.bind(this,rootView);
inflar();
setTextos();
return rootView;
}
(フラグメントをロードするアクティビティで)パルスバックしたときのアクション
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
これを試すことができます
ステップ1:アクティビティでTabselectedメソッドをオーバーライドする
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
try {
if(MyEventsFragment!=null && tab.getPosition()==3)
{
MyEvents.fragmentChanged();
}
}
catch (Exception e)
{
}
mViewPager.setCurrentItem(tab.getPosition());
}
ステップ2:静的メソッドを使用して、フラグメントに必要なことをすべて実行します。
public static void fragmentChanged()
{
Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show();
}
あなたは単純ですできませんフラグメントをフラグメントに追加します。これはFragmentActivityで発生する必要があります。私はあなたがFragmentActivityでLoginFragmentを作成していると仮定します、それでこれを働かせるためにはログインが閉じるときFragmentActivityを通してHomeFragmentを追加する必要があります。
一般的な点は、各FragmentをFragmentManagerに追加する場所からFragmentActivityクラスが必要なことです。 Fragmentクラスの中でこれを行うのは不可能です。
XMLでフラグメントを追加した場合、それらを動的に交換することはできません。何が起こるかというと、彼らは過度にそうなっているので、彼らが期待するようにイベントは発生しません。問題はこの質問に文書化されています。 FragmenManagerの置き換えでオーバーレイが作成されます
Middle_fragmentをFrameLayoutに変えて、以下のようにロードするとあなたのイベントが発生します。
getFragmentManager().beginTransation().
add(R.id.middle_fragment, new MiddleFragment()).commit();
私は子フラグメントで何をしますか:
@Override
public void onDetach() {
super.onDetach();
ParentFragment pf = (ParentFragment) this.getParentFragment();
pf.onResume();
}
そしてParentFragmentのonResumeをオーバーライドします。
フラグメントは常にアクティビティに埋め込まれる必要があり、フラグメントのライフサイクルはホストアクティビティのライフサイクルによって直接影響を受けます。たとえば、アクティビティが一時停止されると、その中のすべてのフラグメントも消去され、アクティビティが破棄されると、すべてのフラグメントも消去されます。
onPause()
メソッドはあなたが使うことができるアクティビティクラスで動作します:
public void onDestroyView(){
super.onDestroyView
}
同じ目的のために。
私はもともと使っていたので、違うコードでも、私はOPと同じ問題を経験しました。
fm.beginTransaction()
.add(R.id.fragment_container_main, fragment)
.addToBackStack(null)
.commit();
の代わりに
fm.beginTransaction()
.replace(R.id.fragment_container_main, fragment)
.addToBackStack(null)
.commit();
"replace"を使用すると、2番目のフラグメントから戻ったときに最初のフラグメントが再作成されるため、onResume()も呼び出されます。
ft.replace
を呼び出すと、(置き換えられたフラグメントの)onPauseと(置き換えられたフラグメントの)onResumeがトリガされます。
私はあなたのコードがhomeフラグメントのlogin_fragment
を膨らませること、そしてまたonCreateViewのビューを返さないことに気付きます。これらがタイプミスであるならば、あなたはこれらのフラグメントがあなたの活動の中からどのように呼ばれているかを示すことができますか?
@ Gor の答えに基づいて、私はKotlinで同じように書いた。このコードをアクティビティのonCreate()
に配置します。それは目に見える1つの断片のために働きます。フラグメント付きのViewPager
がある場合は、前のフラグメントではなくViewPager
のフラグメントが呼び出されます。
supportFragmentManager.addOnBackStackChangedListener {
supportFragmentManager.fragments.lastOrNull()?.onResume()
}
https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 を読んだ後= =新しいフラグメントをreplace
ではなくadd
で添付します。そのため、場合によってはonResume
の必要性がなくなります。
以下のステップに従うと、あなたは必要な答えを得るでしょう
1 - 両方のフラグメントに対して、新しい抽象親を作成します。
2-両者によって実装されるべきであるカスタム抽象メソッドを追加する。
3- 2番目のインスタンスと置き換える前に、現在のインスタンスから呼び出します。
私は自分の活動に使っています - KOTLIN
supportFragmentManager.addOnBackStackChangedListener {
val f = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (f?.tag == "MyFragment")
{
//doSomething
}
}