问题
I'm trying to override the Back Button because it's closing my app when I push on, I have different Fragments:
- Fragment A: Index (When I press back button, it's will close the app)
- Fragment B (When I press back button it will go back to the Fragment A)
- Fragment C (When I press back button it will go back to the Fragment A)
And I have my Main Activity: It manage my Fragments (for have a Navigation Drawer).
I found many posts on this but I can't implement them:
On Fragment B for exemple:
@Override
public void onBackPressed(){
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragmentb); // get the fragment that is currently loaded in placeholder
Object tag = f.getTag();
// do handling with help of tag here
// call super method
super.onBackPressed();
}
It say cannot resolve onBackPressed() and getSupportFragmentManager(), I think I don't use the method correctely, so how to do ?
Activity:
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.graphics.Typeface;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
//Initialisation de l activite avec les donnees necessaires
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// Affichage de la navigation
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Ajout des items
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new Accueil();
title = getString(R.string.title_accueil);
break;
case 1:
fragment = new NosOffres();
title = getString(R.string.title_nosoffres);
break;
case 2:
fragment = new DemandeGratuite();
title = getString(R.string.title_demandegratuite);
break;
case 3:
fragment = new ContactezNous();
title = getString(R.string.title_contact);
break;
case 4:
fragment = new Actualites();
title = getString(R.string.title_actu);
break;
case 5:
fragment = new MentionsLegales();
title = getString(R.string.title_mentions);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
}
@jujyfruits
I tryedbut it doesn't work:
@Override
public void onBackPressed(){
Fragment myFragment = getSupportFragmentManager().findFragmentById(R.id.demande_gratuite);
if (myFragment != null && myFragment.isVisible()) {
AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Reset...");
alertDialog.setMessage("test");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
alertDialog.show();
}
super.onBackPressed();
}
}
@AutonomousApps
public class MainActivity extends AppCompatActivity implements FragmentDrawer.FragmentDrawerListener {
private static String TAG = MainActivity.class.getSimpleName();
private Toolbar mToolbar;
private FragmentDrawer drawerFragment;
//Initialisation de l activite avec les donnees necessaires
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
drawerFragment = (FragmentDrawer)getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
drawerFragment.setUp(R.id.fragment_navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar);
drawerFragment.setDrawerListener(this);
// Affichage de la navigation
displayView(0);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Ajout des items
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public void onDrawerItemSelected(View view, int position) {
displayView(position);
}
private void displayView(int position) {
Fragment fragment = null;
String title = getString(R.string.app_name);
switch (position) {
case 0:
fragment = new Accueil();
title = getString(R.string.title_accueil);
break;
case 1:
fragment = new NosOffres();
title = getString(R.string.title_nosoffres);
break;
case 2:
fragment = new DemandeGratuite();
title = getString(R.string.title_demandegratuite);
break;
case 3:
fragment = new ContactezNous();
title = getString(R.string.title_contact);
break;
case 4:
fragment = new Actualites();
title = getString(R.string.title_actu);
break;
case 5:
fragment = new MentionsLegales();
title = getString(R.string.title_mentions);
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
fragmentTransaction.addToBackStack("name");
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
@Override
public void onBackPressed(){
FragmentManager mgr = getSupportFragmentManager();
if (mgr.getBackStackEntryCount() == 0) {
super.onBackPressed();
}else{
mgr.popBackStack();
}
}
回答1:
This is what I use when navigating between fragments:
MainActivity.java:
@Override
public void onBackPressed() {
// note: you can also use 'getSupportFragmentManager()'
FragmentManager mgr = getFragmentManager();
if (mgr.getBackStackEntryCount() == 0) {
// No backstack to pop, so calling super
super.onBackPressed();
} else {
mgr.popBackStack();
}
}
EDIT the second: Please note that you ONLY want to call super.onBackPressed()
if you haven't already handled it (by, for example, popping the fragment manager's backstack).
For that to work, you have to add new fragments to your FragmentManager
's backstack (addToBackStack()
). For example (also in MainActivity.java):
private void displayView(int position) {
Fragment fragment = ...; // YOUR CODE HERE
if (fragment != null) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container_body, fragment);
// ADD THIS LINE
fragmentTransaction.addToBackStack("name"); // name can be null
fragmentTransaction.commit();
// libelle du toolbar
TextView titlet;
titlet = (TextView) findViewById(R.id.main_toolbar_title);
titlet.setText(title);
titlet.setTypeface(Typeface.createFromAsset(getAssets(), "fonts/GothamBook.ttf"));
}
}
EDIT the third (7/28): In your onCreate(Bundle)
method, you do your very first fragment transaction by calling your displayView(int)
method. displayView(int)
always adds its fragment transactions to the backstack. This is not what you want. The very first fragment transaction should use fragmentTransaction.**add**(int, Fragment)
and should not call addToBackStack(String)
. Every transaction after the first should call fragmentTransaction.**replace**(int, Fragment)
and should call addToBackStack(String)
. The reason for this is that you first transaction is basically "adding" a fragment (your UI) to an empty container (it is not "replacing" another fragment). When this transaction is on the backstack, that means that the empty-container state is also on the backstack. So when you pop that last transaction, it displays a blank UI.
EDIT the first: When you call addToBackStack(String name) on a FragmentTransaction object (which you obtain by calling getFragmentManager().beginTransaction()), then you are adding a FragmentTransaction
to your FragmentManager
s 'backstack'. What my code does is check the size of the backstack by calling getFragmentManager.getBackStackEntryCount(). If that number is greater than zero, then we know we have FragmentTransaction
s on the backstack. In such a case, you can call getFragmentManager.popBackStack(), which will pop the last transaction off the backstack--in other words, returning your app to the last Fragment that was on display.
If the backstack entry county equals 0, then that means you're at your Fragment A, and you should instead call super.onBackPressed()
, and this will cause the app to exit.
回答2:
onBackPressed()
and getSupportFragmentManager()
are methods from the Activity class, not Fragment, so you have to implement this on the Activity and not the Fragment.
If you want to implement a particular behaviour just for one fragment you can check what's the current visible fragment and then implement your behaviour. Like this:
@Override
public void onBackPressed(){
MyFragment myFragment = (MyFragment)getFragmentManager().findFragmentByTag("YOUR_FRAGMENT");
if (myFragment != null && myFragment.isVisible()) {
// the code for whatever behaviour you want goes here
}
else
super.onBackPressed();
}
Another possible, probably simpler way would be to use some flag in the Activity that you activate when you add the fragment and then read from the onBackPressed()
.
EDIT ON RESPONSE TO BENJY'S EDIT
Notice that you're not exactly using the code I posted. You're using findFragmentById()
which doesn't apply to every situation and I can't tell if it's right for your code.
You should use findFragmentByTag
which applies to any kind of fragment transaction.
Just add a tag to your fragment when you do the transaction, like this:
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment(), "FRAGMENT_TAG")
.commit();
Then when you try to get back the Fragment in your onBackPressed()
, you get it looking for that tag:
PlaceholderFragment myFragment = (PlaceholderFragment) getSupportFragmentManager()
.findFragmentByTag("FRAGMENT_TAG");
Make this change it has to work.
来源:https://stackoverflow.com/questions/31590919/replace-fragment-with-another-on-back-button