Fragment Back stack from second fragment to first fragment - android

I have viewpager tab fragment and from one tabb fragment on button click it open another fragment and another second fragment i want to add event of backpress as i am doing backpress it exiting application as i have written code of Double back press exit code in my root fragment and i dont want this code to call in my another second fragment as i want simply one step back to my previous fragment
As here is the code
R.id.Recharge -> {
val pl = Payment_History()
fragmentTransaction = fragmentManager!!.beginTransaction()
fragmentTransaction.replace(R.id.frame_container, paypal)
fragmentTransaction.addToBackStack(null)
fragmentTransaction.commit()
}
In Payment history i am calling on Back press override function
override fun onBackPressed(): Boolean {
super.onBackPressed()
}
and on clicking on Paymenthistory it called exit code from application. i want that it back to previous fragment. As I have written this fragment code but not working.
Any one have idea how to back second nested fragment to previous fragment.
My OnBackPress code in my MainActivity
override fun onBackPressed() {
// TODO Auto-generated method stub
try {
if (getFragmentManager().getBackStackEntryCount() == 0) {
if (doubleBackToExitPressedOnce) {
//super.onBackPressed();
val startMain = Intent(Intent.ACTION_MAIN)
startMain.addCategory(Intent.CATEGORY_HOME)
startMain.flags = Intent.FLAG_ACTIVITY_NEW_TASK
pref!!.setLoggedIn(true)
startMain.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK
startMain.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
startActivity(startMain)
return
}
this.doubleBackToExitPressedOnce = true
Toast.makeText(this, "Please click again to exit", Toast.LENGTH_SHORT).show()
Handler().postDelayed({ doubleBackToExitPressedOnce = false }, 2000)
}
}catch (e:Exception){
println("homemessage"+ e.message)
}
}

Add your fragment to backstack and then in your onBackPressed method do something like this:
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
this.finish();
}
}
For more information see this
Hope this is what you are looking for and it helps you.

Try this (Instead of "replace" use "add")
fragmentTransaction = fragmentManager!!.beginTransaction()
fragmentTransaction.add(R.id.frame_container, paypal)
fragmentTransaction.addToBackStack(null)
fragmentTransaction.commit()
and
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else {
this.finish();
}
}

if fragment within fragment back use this code onbackpreesed method
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if(getFragmentManager().getBackStackEntryCount() == 1) {
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Check out")
.setMessage("want to do check out?")
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
closeApp();
}
})
.setNegativeButton("No",null)
.show();
}
else {
super.onBackPressed();
}
}
each fragment store in a stack
FragmentManager ff=getFragmentManager();
ff.beginTransaction().replace(R.id.main_content,new home()).addToBackStack(null).commit();
it's work in my project

I used this in Activity
Step 1:
Created a global variable for boolean
private boolean doubleBackToExitPressedOnce = false;
Step 2:
Then in onBackPress() method of activity
i did this
#Override
public void onBackPressed() {
if (mViewPager.getCurrentItem() > 0) {
//if any tab selected instead of tab 1
mDoubleBackToExitPressedOnce = false;
} else if (mViewPager.getCurrentItem() == 0) {
//if tab 1 selected
mDoubleBackToExitPressedOnce = true;
if (mDoubleBackToExitPressedOnce)
super.onBackPressed();
}
mViewPager.setCurrentItem(0);//go to tab 1
}

I was also Struggling in this regard. after a lot of research i found a solution that we have to call super.onBackPressed() where our last or home fragment is Active
Solution
override fun onBackPressed() {
val activeFragment = this.supportFragmentManager.
findFragmentById(R.id.frame_layout)
if (activeFragment is HomeFragment){
startActivity(Intent(this, DashBoardActivity::class.java))
finish()
super.onBackPressed()
}
else
{
val ft: FragmentTransaction
=supportFragmentManager.beginTransaction()
//should not call super.onBackPressed()
switchFragment(ft)
}
//nor here you should call super.onBackPressed()
}
and the switchFragment function is
fun switchFragment(ft:FragmentTransaction) {
try {
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right)
if (supportFragmentManager.findFragmentById(R.id.frame_layout) == null) {
ft.add(R.id.frame_layout, HomeFragment())
} else {
ft.replace(R.id.frame_layout, HomeFragment())
println("Comess")
}
ft.addToBackStack(null)
ft.commit()
} catch (e: Exception) {
e.printStackTrace()
}
}

Related

I want to close the app but do not go back to the previous Activity

I used an activity and several pieces in my app
sometimes when I'm on the first page (activity) and back pressed not going out of app and returns to the fragment or the same page
When this happens I've done a lot of work in the program
I used this code to fix this problem but
it also applied to the fragments
#Override
public void onBackPressed() {
this.finish();
}
Why returns to the fragment or the same page
How this problem is solved
I'm using this now
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else if (!doubleBackToExitPressedOnce) {
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Click to exit again", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
} else {
super.onBackPressed();
return;
}
}
Way is going to be a fragment
TabirFragment tabirFragment = new TabirFragment();
Bundle bundle = new Bundle();
bundle.putInt("id", id);
bundle.putString("name", name);
tabirFragment.setArguments(bundle);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction().addToBackStack(null);
transaction.replace(R.id.main_activity, tabirFragment).commit();
If you have multiple activities on the stack, then:
finish() - finishes the activity where it is called from and you see
the previous activity.
There is also system.exit but that would not work in your case:
System.exit(0) - restarts the app with one fewer activity on the
stack. So, if you called ActivityB from ActivityA, and System.exit(0)
is called in ActivityB, then the application will be killed and
started immediately with only one activity ActivityA
I recommend you use finishAffinity(). It will finish the current activity as well as all activities immediately below it. I remind you that it is supported by only API level 16+
several pieces what? fragments, getting trouble to understand, anyway if you want to manage frag and onBackPress, use this
private void setUpBackStackListener() {
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
Fragment currentFragment = getFragmentManager().findFragmentById(R.id.am_frameLayout);
if (currentFragment != null) {
int myCount = getFragmentManager().getBackStackEntryCount();
if (LOG_DEBUG) Log.e(TAG, "backStackCount : " + myCount);
String currentFragName = currentFragment.getClass().getSimpleName();
if (currentFragName.equalsIgnoreCase(FragOne.class.getSimpleName())) {
shouldExit = true;
} else if (currentFragName.equalsIgnoreCase(FragTwo.class.getSimpleName())) {
shouldExit = false;
}
}
}
}
});
}
#Override
public void onBackPressed() {
if (shouldExit == true) {
if (LOG_DEBUG)
Log.e(TAG, " Yeah exit douche:" + shouldExit + " isLastEntry : Testing :" + isLastEntry);
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
,if this not you seeking, you might want to clear what you want in a bit subtle way
When you used multiple fragment and activity When you switch activity by using method startActivity(), always use method finish(); when you back pressed then you will never get multiple activity and fragment and use onBackPressed method on main activity.
boolean doubleBackToExitPressedOnce=false;
#Override
public void onBackPressed() {
//Checking for fragment count on backstack
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
} else if (!doubleBackToExitPressedOnce) {
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this,"Please click back again to exit.", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
} else {
super.onBackPressed();
return;
}
}
The easiest solution i can give you is to keep no-history for the activity in the manifest file. and then override the back method for each activity.
<activity
android:name=".example"
android:noHistory="true">
</activity>

Onbackpressed redirect to particular fragment

In my app i have navigation drawer,So i have one MainActivity and rest are fragments. My app is working fine. Whenever i press back button it redirect to previous fragment.it works fine.but what i want is after successful payment i am displaying Successful payment page,on this page when user press back button i want to redirect to HomeFragment,but right now it goes to Placeorder fragment.
#Override
public void onBackPressed() {
if(getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
}
else {
getFragmentManager().popBackStack();
}
}
Override your onBackPress method:
#Override
public void onBackPressed() {
if (fragment != null && fragment.getChildFragmentManager().getBackStackEntryCount() > 0){
fragment.getChildFragmentManager().popBackStack();
}else {
super.onBackPressed();
}
}
One way would be saving previous fragment (previousFragment) variable while opening new fragment and making it null when you are in first or placeholder fragment .... then check value of previousFragment inside onBackPressed method , if null perform exit operation else replace fragment with previousFragment by which you will get back to previous fragment on back press.
You should simulate function as below in abstract class fragment
/**
* Handle "Back" key pressed.
* #return TRUE if the "Back" key pressed was handled. FALSE indicate it's not handled and parent class can handle it.
*/
public abstract boolean onBackPressed()
And in MainActivity, you will handle this function
#Override
public void onBackPressed() {
if (mSelectedFragment != null && mSelectedFragment.onBackPressed()) {
return;
} else {
super.onBackPressed
}
}
inside your onBackPressed() do like this:
#Override
public void onBackPressed() {
if(getSupportFragmentManger.findFragmentByTag("paymentFragment") != null){
//add homeFragment;
}
else{
if(getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
}
else {
getFragmentManager().popBackStack();
}
}
}
you can set some global variable (true when payment is success else false) in Application class and in onbackpressed of your activity just check that variable is true or not.Then in backpressed of your activity call this function.
public void clearBackStack() {
FragmentManager manager = getSupportFragmentManager();
if (manager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
Use:
fragmentTransaction.replace(R.id.fragment_container, mFeedFragment);
fragmentTransaction.commit();
Don't do this:
fragmentTransaction.addToBackStack(null);
Follow this simple method
declare an integer as
public int count;
initialise this count as count=0 in your main page
now include this in your main activity
#Override
public void onBackPressed() {
if (count == 1) {
if (exit) {
super.onBackPressed();
return;
} else {
Toast.makeText(this, "Press Back again to Exit.", Toast.LENGTH_SHORT).show();
exit = true;
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
exit = false;
}
}, 2000);
}
}else {
toolbar.setTitle("Home");
mDrawerLayout.closeDrawers();
count=1;
display(0);
}
}

Doesn't change fragment backstack size when I press back button in Actvity

This is my code:
FragmentManager fragmentManager = getSupportFragmentManager();
try {
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
When I am adding first fragment, my method getSupportFragmentManager().getBackStackEntryCount() returns 0.
When I am adding second fragment getBackStackEntryCount() returns 1, but when I am pressing back button getBackStackEntryCount() still returns 1.
Why?
UPD -
#Override
public void onBackPressed() {
super.onBackPressed();
updateToolbar(); // here I check backstackCount and update Toolbar
}
UPD2 -
private void updateToolbar() {
if (getSupportFragmentManager().getBackStackEntryCount()() > 0) {
showBackButtonOnToolBar();
} else {
showProfileButtonOnToolBar();
}
}
You will have to call popBackStack() from your onBackPressed():
#Override
public void onBackPressed()
{
if (getSupportFragmentManager().getBackStackEntryCount() > 0)
{
getSupportFragmentManager().popBackStack();
}
else
{
super.onBackPressed();
}
}
Update:
add your line updateToolbar(); below pop call inside if statement.
Answer is similar to Sarthak's, however instead of calling:
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
}
else {
super.onBackPressed();
}
call the instance of YOUR fragment manager i.e fragmentManager
like so:
if (fragmentManager.getBackStackEntryCount() > 0) {
fagmentManager.popBackStack();
}
else {
super.onBackPressed();
}
UPDATE:
Probably best to create a FragmentManager field, initialise it in the onCreate of your activity and then use that throughout all fragment transactions, adding to back stack and so on.

onBack pressed in activity and fragment

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.

Popbackstack Finishes Activity in OnBackPressed

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.

Categories

Resources