i have activity1 takes me to activity2 that takes me to fragment. i would like from fragment to go back to activity2
public void onBackPressed() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
}
else
super.onBackPressed();
}
While adding fragment from activity2 add it to backstack like this
getSupportFragmentManager().beginTransaction()
.replace(R.id.frame_layout, new SampleFragment())
.addToBackStack(SampleFragment.class.getSimpleName())
.commit();
And onBackPressed check if the fragment is present in backstack and pop it
#Override
public void onBackPressed() {
if(getSupportFragmentManager().getBackStackEntryCount()>0){
Fragment fragment=getSupportFragmentManager().findFragmentById(R.id.YOUR_FRAME_LAYOUT_ID);
if(fragment!=null && fragment.getClass().getSimpleName().equalsIgnoreCase(SampleFragment.class.getSimpleName())){
getSupportFragmentManager().popBackStackImmediate();
}
}else {
super.onBackPressed();
}
}
on fragments get the backpressed event and there call the
getactivity().getsupportfragmentmanager().popbackstack();
Add that fragment transaction to backstack.
Related
Navigation drawer with fragments. I have placed one fragment on main activity. But if i back press the same fragment comes again. How can I handle this??
and secondly how to implement onBackpressed in fragments??
Can anybody help me out?
in onCreate of main activity I have
FragmentTransaction tx = getFragmentManager().beginTransaction();
tx.replace(R.id.mainFrame, new PlaceOrderFragment());
tx.commit();
and in back press of it I have
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
First you need to add the fragmnet to back stack so we could retrieve it later in onBackPressed()
Replace your fragmnet transaction with this
FragmentTransaction tx = getFragmentManager().beginTransaction();
tx.replace(R.id.mainFrame, new PlaceOrderFragment());
// HERE WE WILL ADD FRAGMENT TO BACKSTACK SO WE COULD GET BACK TO IT
tx.addToBackStack(null);
tx.commit();
Replace your onBackPressed with this
#Override
public void onBackPressed() {
// CHECKS HOW MANY FRAGMENTS ARE IN THE BACKSTACK
int count = getFragmentManager().getBackStackEntryCount();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (count == 0) {
// IF NO FRAGMENT IN THE BACKSTACK CALL
super.onBackPressed();
} else {
// GET THE LAST OPENED FRAGMENT
getFragmentManager().popBackStack();
}
}
}
You can do this using Interface. That interface will implemented in each fragment. Here is a simple example:
public interface OnBackPressedListener {
void onBackPressed();
}
Here, if you implement this interface in your fragment then you will found this method:
#Override
public void onBackPressed() {
getActivity().finish(); // Or Do your specific task
}
Now your Activity that holds that fragment , that should use onBackPressed() callback. Write bellow code in that method
#Override
public void onBackPressed() {
if (YOUR_DRAWER.isDrawerOpen(GravityCompat.START)) {
YOUR_DRAWER.closeDrawer(Gravity.LEFT); //CLOSE Nav Drawer!
return;
}
Fragment fragment=getYourVisibleFragment();
if(fragment!=null){
((OnBackPressedListener)fragment).onBackPressed();
}else{
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
If you want to get Visible fragment then just use this method
public <F extends Fragment> F getVisibleFragment() {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null && fragment.isVisible()) {
return (F) fragment;
}
}
}
return null;
}
That's it :)
FragmentTransaction tx = getFragmentManager().beginTransaction();
tx.replace(R.id.mainFrame, new PlaceOrderFragment()).addToBackStack("your tag");
tx.commit();
Override onBackPress() and try following code.
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//your other utility code if needed
} else {
getFragmentManager().popBackStack();
}
}
Hope this will work for you.
Replace ypu fragment in onCreate with fragment id , and then implement onBackpressed on the same activity and find that fragment with id and check is it visible or null and then perform operations based on it.
hope you got this.
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry bSE = getSupportFragmentManager().getBackStackEntryAt(getSupportFragmentManager().getBackStackEntryCount() - 1);
Fragment frag = getSupportFragmentManager().findFragmentByTag(bSE.getName());
if (frag instanceof BackButtonBlocker)
{
BackButtonBlocker callback = (BackButtonBlocker) frag;
callback.onBackPressed();
}
else {
getSupportFragmentManager().popBackStack();
}
} else {
super.onBackPressed();
}
}
BackButtonBlocker interface is for callback. my fragment implements BackButtonBlocker but sometimes onBackPressed not occurs (onKeyUp as well).
when I open navigation drawer, onBackPressed and full logic works exactly.
why should activity lose focus?
android.support.v4.app.Fragment
public interface BackButtonBlocker{ void onBackPressed();}
take out super.onBackPressed(); from else{}
What I have done is that, I have not implemented any interface to handle back pressed see below.
#Override
public void onBackPressed() {
if (getDrawerLayout().isDrawerOpen(GravityCompat.START)) {
closeLeftMenu();
}
else {
if (getSupportFragmentManager().getBackStackEntryCount() > 1) {
super.onBackPressed();
} else {
finish(); // Means it is home and you can exit it from here.
}
}}
When drawer is open just close it then use your code.
I fixed this issue by adding setFocusableInTouchMode(true); requestFocus(); on Mainactivity's container view
I want to return back to MainActivity on clicking back button from each fragment and destroy Activity after returning back to the MainActivity.
I have tried something but it is continuously calling the fragment but not destroying it.
#Override
public void onBackPressed() {
startActivity(new Intent(this,MainActivity.class));
finish();
}
Do something like this in your MainActivity:
#Override
public void onBackPressed(){
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.frameLayout);
if (fragment instanceof YourFragment || fragment instanceof YourOtherFragment) {
getSupportFragmentManager().beginTransaction().replace(R.id.frameLayout, new MainScreenFragment()).commit();
}else {
super.onBackPressed();
}
}
Add this to the Mainactivity
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
this.finish();
} else {
getFragmentManager().popBackStack();
}
}
I have an Activity with two Fragments (List & Details), in onCreate(), I start the List Fragment if savedInstance is null like so
public static final int CLIENT_LIST_FRAGMENT = 1;
public static final int CLIENT_DETAILS_FRAGMENT = 2;
private int currentFragment = 0;
if (savedInstanceState == null) {
//On first run, start the list fragment
if (currentFragment == 0) {
ClientListFragment listFrag = new ClientListFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container_client, listFrag, Constants.CLIENT_LIST_FRAGMENT_TAG)
.commit();
currentFragment = CLIENT_LIST_FRAGMENT;
} else {
switch (currentFragment) {
case CLIENT_LIST_FRAGMENT:
addListFragment();
break;
case CLIENT_DETAILS_FRAGMENT:
addDetailsFragment(0);
break;
}
}
}
And here is the method that add the DetailsFragment and ListFragment as needed
private void addListFragment(){
ClientDetailsFragment listFrag = new ClientDetailsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.container_client, listFrag, Constants.CLIENT_LIST_FRAGMENT_TAG)
.addToBackStack("details")
.commit();
currentFragment = CLIENT_LIST_FRAGMENT;
}
private void addDetailsFragment(long companyId){
ClientDetailsFragment detailsFrag = ClientDetailsFragment.newInstance(companyId);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container_client, detailsFrag, Constants.CLIENT_DETAILS_TAG)
.addToBackStack(null)
.commit();
currentFragment = CLIENT_DETAILS_FRAGMENT;
}
This works as expected except that when I click the back button from the Details Fragment, instead of taking me back to the List Fragment, it actually finishes the Activity. It goes back to the List Fragment for a split second and then finishes the host Activity and goes back to the calling Activity. How can I stop this behavior, after going through a lot of onBackpress related question on SO here is my overide of the onBackPressed
#Override
public void onBackPressed() {
if (currentFragment == CLIENT_DETAILS_FRAGMENT){
getSupportFragmentManager().popBackStackImmediate();
}else {
super.onBackPressed();
}
}
Thanks
Activity onBackPressed() should be:
For android.support.v4.app.Fragment
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 1)
getSupportFragmentManager().popBackStack();
else
finish();
}
For android.app.Fragment
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 1)
getFragmentManager().popBackStack();
else
finish();
}
I usually check whether the current fragment instance belongs to the fragment that invoked onBackPressed(). This code is untested; it's just to give you an idea on how to proceed. I hope you are not calling this.finish() on this Activity.
#Override
public void onBackPressed() {
Fragment fragment = getSuportFragmentManager().findFragmentByTag(Constants.CLIENT_DETAILS_TAG);
if (fragment instanceof ClientDetailsFragment) {
getSupportFragmentManager().popBackStackImmediate();
}
else {
super.onBackPressed();
}
}
Let me know if that helps.
Good Lord, I was chasing the wrong shadow for two days. I was listening, handling and overriding the wrong event.
This SO question saved me Why is onBackPressed() not being called?
And the gist is "onBackPressed() is invoked when user clicks on a hardware back button (or on the 'up' button in the navigation bar), not the button in the action bar. For this one you need to override onOptionsItemSelected() method. Example:"
I was catching this event the fragment and calling getActivity.onBackpressed. When I stopped this, it became obvious to me that the onBackPressed is not being called. Here is my solution, may not be optimal but it works
if (item.getItemId() == android.R.id.home){
if (currentFragment == CLIENT_DETAILS_FRAGMENT){
getSupportFragmentManager().popBackStackImmediate();
currentFragment = CLIENT_LIST_FRAGMENT;
return true;
}
}
if (currentFragment == 0) {
ClientListFragment listFrag = new ClientListFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container_client, listFrag, Constants.CLIENT_LIST_FRAGMENT_TAG)
.commit();
currentFragment = CLIENT_LIST_FRAGMENT;
}
while changing this add to addToBackStack()
and,
change onBackPressed() like,
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 1) {
MainActivity.this.finish();
}
else {
getFragmentManager().popBackStack();
}
}
Hope, this will work.
My application structure look like:
SplashActivity -> MainActivity -> (switching between many fragments)
What I expect: finish application from main activity when fragment back stack count is zero. Here is my try:
In SplashAcitivty
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getIntent().getBooleanExtra("exit", false)) {
finish();
}
}
In MainActivity:
#Override
public void onBackPressed() {
// I need to implement this method
if( backstackCount() == 0){
Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra(SplashActivity.EXIT_KEY, true);
startActivity(intent);
}else{
super.onBackPressed();
}
}
So, please tell me how can I determine the back stack when it 's empty? Because I use SlideMenu library, all of my fragments switch many times, and they are added to back stack when switching. Look like this one:
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack(null)
.commit();
Here is my code. It works fine for me:
#Override
public void onBackPressed() {
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
if (backStackEntryCount == 0) {
goBack(); // write your code to switch between fragments.
} else {
super.onBackPressed();
}
}