Ich habe mehrere Fragmente in einer Aktivität. Klicken Sie auf eine Schaltfläche, um ein neues Fragment zu erstellen, und fügen Sie es dem Backstack hinzu. Ich habe natürlich erwartet, dass die onPause()
Methode des aktuellen Fragments und onResume()
des neuen Fragments aufgerufen wird. Nun, es passiert nicht.
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();
}
}
Was ich erwartet hatte, war
onPause()
von LoginFragment und onResume()
von HomeFragment abgerufen namensonPause()
von HomeFragment und onResume()
von LoginFragment wird gerufen.Was ich bekomme ist
Ist das das normale Verhalten? Warum wird onResume()
of LoginFragment nicht aufgerufen, wenn ich die Zurück-Taste drücke.
Die Fragmente onResume()
oder onPause()
werden nur aufgerufen, wenn die Aktivitäten onResume()
oder onPause()
aufgerufen werden .. .. Sie sind fest mit der Activity
gekoppelt.
Lesen Sie den Abschnitt Umgang mit dem Fragment-Lebenszyklus dieses Artikels .
ft2.replace()
verwendet haben, wird die Methode FragmentTransaction.remove()
aufgerufen und Loginfragment
entfernt. Siehe this . Daher wird onStop()
von LoginFragment
anstelle von onPause()
aufgerufen. (Da das neue Fragment das alte vollständig ersetzt).ft2.addtobackstack()
verwendet haben, wird der Status von Loginfragment
als Bundle gespeichert. Wenn Sie in HomeFragment
auf die Schaltfläche "Zurück" klicken, wird onViewStateRestored()
gefolgt von aufgerufen onStart()
von LoginFragment
. Schließlich wird onResume()
nicht aufgerufen.Wenn Sie das Fragment wirklich in einem anderen Fragment ersetzen möchten, sollten Sie Nested Fragmente verwenden.
In Ihrem Code sollten Sie ersetzen
final FragmentManager mFragmentmanager = getFragmentManager();
mit
final FragmentManager mFragmentmanager = getChildFragmentManager();
Hier ist meine robustere Version von Gors Antwort (die Verwendung von fragments.size () ist unzuverlässig, da die Größe nicht verringert wird, nachdem das Fragment abgelegt wurde)
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.
}
}
}
}
});
Und die Methode '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;
}
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
}
}
});
seien Sie jedoch vorsichtig, wenn mehr als ein Fragment sichtbar ist
Ich habe einen Code, der Ihrem sehr ähnlich ist, und ob es onPause () und onResume () funktioniert. Beim Ändern des Fragments werden diese Funktionen jeweils aktiviert.
Code im Fragment:
@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");
}
Log bei Fragmentwechsel:
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
Fragment 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;
}
Aktion, wenn ich zurückspringe (in der Aktivität, in der ich das Fragment lade):
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
Sie können dies versuchen,
Schritt 1: Überschreiben Sie die tabellierte Methode in Ihrer Aktivität
@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());
}
Schritt 2: Verwenden Sie statische Methoden, was Sie in Ihrem Fragment wollen.
public static void fragmentChanged()
{
Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show();
}
Sie können einfach kann nicht einem Fragment ein Fragment hinzufügen. Dies muss in der FragmentActivity geschehen. Ich gehe davon aus, dass Sie das LoginFragment in einer FragmentActivity erstellen. Damit dies funktioniert, müssen Sie das HomeFragment über die FragmentActivity hinzufügen, wenn die Anmeldung geschlossen wird.
Der allgemeine Punkt ist, dass Sie eine FragmentActivity-Klasse benötigen, von der Sie jedes Fragment zum FragmentManager hinzufügen. Es ist nicht möglich, dies innerhalb einer Fragment-Klasse durchzuführen.
Wenn Sie das Fragment in XML hinzufügen, können Sie sie nicht dynamisch vertauschen. Was passiert, ist sie übermäßig, so dass Ereignisse nicht wie erwartet ausgelöst werden. Das Problem ist in dieser Frage dokumentiert. FragmenManager ersetzt Overlay
Verwandeln Sie middle_fragment in ein FrameLayout und laden Sie es wie unten, und Ihre Ereignisse werden ausgelöst.
getFragmentManager().beginTransation().
add(R.id.middle_fragment, new MiddleFragment()).commit();
Was mache ich im Kindfragment:
@Override
public void onDetach() {
super.onDetach();
ParentFragment pf = (ParentFragment) this.getParentFragment();
pf.onResume();
}
Überschreiben Sie dann onResume auf ParentFragment
Ein Fragment muss immer in eine Aktivität eingebettet sein, und der Lebenszyklus des Fragments ist direkt vom Lebenszyklus der Host-Aktivität betroffen. Wenn zum Beispiel die Aktivität angehalten wird, sind alle Fragmente darin, und wenn die Aktivität zerstört wird, sind dies auch alle Fragmente
Die onPause()
-Methode funktioniert in der Aktivitätsklasse, die Sie verwenden können:
public void onDestroyView(){
super.onDestroyView
}
für den gleichen Zweck ..
Obwohl mit anderem Code, hatte ich dasselbe Problem wie das OP, da ich es ursprünglich verwendet habe
fm.beginTransaction()
.add(R.id.fragment_container_main, fragment)
.addToBackStack(null)
.commit();
anstatt
fm.beginTransaction()
.replace(R.id.fragment_container_main, fragment)
.addToBackStack(null)
.commit();
Mit "replace" wird das erste Fragment neu erstellt, wenn Sie vom zweiten Fragment zurückkehren. Daher wird onResume () auch aufgerufen.
Der Aufruf von ft.replace
sollte die onPause (des ersetzten Fragments) und onResume (des ersetzenden Fragments) auslösen.
Ich stelle fest, dass Ihr Code login_fragment
auf dem Ausgangsfragment aufbläst und die Ansichten in onCreateView nicht zurückgibt. Wenn dies Tippfehler sind, können Sie dann zeigen, wie diese Fragmente aus Ihrer Aktivität heraus aufgerufen werden?
Basierend auf der Antwort von @Gor schrieb ich ähnlich in Kotlin. Fügen Sie diesen Code in onCreate()
einer Aktivität ein. Es funktioniert für ein Fragment sichtbar. Wenn Sie ViewPager
mit Fragmenten haben, wird ViewPager
s Fragment aufgerufen, nicht ein vorheriges.
supportFragmentManager.addOnBackStackChangedListener {
supportFragmentManager.fragments.lastOrNull()?.onResume()
}
Nach dem Lesen von https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6 habe ich verstanden, dass es in vielen Situationen besser wäre, neue Fragmente anzufügen mit replace
, nicht add
. In einigen Fällen wird also ein Bedarf in onResume
verschwinden.
Befolgen Sie die nachstehenden Schritte, und Sie erhalten die erforderliche Antwort
1- Erstellen Sie für beide Fragmente ein neues abstraktes übergeordnetes.
2- Fügen Sie eine benutzerdefinierte abstrakte Methode hinzu, die von beiden implementiert werden soll.
3- Rufen Sie die aktuelle Instanz auf, bevor Sie sie durch die zweite Instanz ersetzen.
Ich benutze in meiner Tätigkeit -KOTLIN
supportFragmentManager.addOnBackStackChangedListener {
val f = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (f?.tag == "MyFragment")
{
//doSomething
}
}