Ok i have an activity with one main fragment, that has a menu on it. When a user clicks on a menu item another fragment is animated into the screen, with this code:
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out);
ft.hide(getFragmentManager().findFragmentByTag("menu_fragment"));
Fragment opisFragment = getFragmentManager().findFragmentByTag("opis_fragment");
if (opisFragment == null) {
opisFragment = new OpisFragment();
ft.add(R.id.p_container, opisFragment, "opis_fragment");
ft.commit();
} else {
ft.show(opisFragment);
}
Note: pr_fragment is the tag of the current fragment, the one that has the menu.
Now, this works well, but when i'm on the second fragment i want to add the functionality, that when the user clicks the back button it will show the first fragment. With this code, when i click back it exits the activity alltogether.
Thank you for the help!
All you need is to use addToBackStack(String name) of FragmentTransaction
// Showing menu fragment also added in backstack
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out)
.add(R.id.p_container, menuFragment, "menu_fragment")
.addToBackStack("menu_fragment")
.commit();
// Showing opis fragment also added in backstack
FragmentTransaction ft2 = getFragmentManager().beginTransaction();
ft2.setCustomAnimations(R.anim.push_left_in, R.anim.push_left_out)
.add(R.id.p_container, opisFragment, "opis_fragment")
.addToBackStack("opis_fragment")
.commit();
Assuming "opis fragment" is in foreground, when you press back button, "menu_fragment" will be displayed back to the foreground, pressing back button again will exit the activity.
With this code, when i click back it exits the activity alltogether.
Normal because there is just your activity in your app stack. the addToBackStack() method is what you are looking for.
if (opisFragment == null) {
opisFragment = new OpisFragment();
ft.add(R.id.p_container, opisFragment, "opis_fragment");
ft.addToBackStack("tag"); // <<< this line
ft.commit();
}
From the doc :
Before you call commit(), however, you might want to call addToBackStack(), in order to add the transaction to a back stack of fragment transactions. This back stack is managed by the activity and allows the user to return to the previous fragment state, by pressing the Back button.
in mainactivity you can check fragments count if fragments count more than one we will show back button
if(getSupportFragmentManager().getBackStackEntryCount() > 0)
{
mDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayShowHomeEnabled(false);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
else
{
mDrawerToggle.setDrawerIndicatorEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
getSupportActionBar().setHomeButtonEnabled(false);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
Related
I used 3 fragments in one activity using framelayout from 3rd fragment,it should go to one activity then on back press of that activity,it should redirect to that 3rd fragment and from on back press from 3rd fragment it should redirect to 1st fragment without blank screen? .i got blank screen and looping
Override onBackPressed() and process the replace inside.
#Override
public void onBackPressed() {
//Check current fragment
Fragment f = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
if(f instanceof FragmentThird) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack if needed
transaction.replace(R.id.fragment_container, fragmentFirst);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
return;
}
I have an application with 4 fragments: MainFragment, ActionFragment, DoneFragment, FailedFragment. When application launched it shows MainFragment. Than application receive some event and show ActionFragment with two buttons 'yes' and 'no'. If user press 'yes', applicaiton shows DoneFragment, otherwise FailedFragment. When user press one time to back button on ActionFragment, DoneFragment or FailedFragment application must show MainFragment.
Improtant: if ActionFragment, DoneFragment or FailedFragment already opened and some event is occure again, application should show ActionFragment fragment with new event data.
So, I need:
if ActionFragment, DoneFragment or FailedFragment already opened and event occur, I should replace top fragment with ActionFragment
Otherwise I should simply add ActionFragment.
I am trying:
fun addOrReplaceFragment(fragment: Fragment, tag: String) {
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
val previous = fragmentManager.findFragmentByTag(tag)
if (previous == null) {
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE)
fragmentTransaction.add(R.id.main_fragment_container, fragment, tag)
fragmentTransaction.addToBackStack(tag)
} else {
fragmentManager.popBackStack(previous.id, 0)
fragmentTransaction.remove(previous)
fragmentTransaction.add(R.id.main_fragment_container, fragment, tag)
fragmentTransaction.addToBackStack(tag)
}
fragmentTransaction.commitAllowingStateLoss()
}
// ...
addOrReplaceFragment(ActionFragment(), "singleTag")
// ...
addOrReplaceFragment(DoneFragment(), "singleTag")
// ...
addOrReplaceFragment(FailedFragment(), "singleTag")
Here is popBackStack() doesn't work. When ActionFragment is opened, DoneFragment or FailedFragment just adding above. And user have to press back two times to get back to MainFragment.
I am find solution change popBackStack() to popBackStackImmediate(). It works well, but if activity is minimized it produce crash with IllegalStateException, because popBackStackImmediate() cannot be called after onSaveInstanceState().
How to replace top fragment and avoid IllegalStateException?
Try this :
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.FragmentToBeReplaced,theFragmentToBeAdded);
ft.commit();
https://developer.android.com/reference/android/app/FragmentManager.html#isStateSaved()
Use isStateSaved to avoid losing state when a transaction happened.
And I think Android navigation component might be easier way to navigate between fragments.
I have a main activity that exists out of three fragments. Fragment 2 is the main fragment. On fragment 3 I have a button. Once I click the button it directs the user to a ChatActivity. The ChatActivity has an onBackButtonPressed that should return the user back to fragment 3. However, it seems that it would always return the user to fragment 2 (the main fragment).
How can I bring the user to the fragment they last visited, or at least back to fragment 3?
Edit:
I added this block of code in the button onClick function:
ChatFragment fragment = new ChatFragment();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.main_tabPager, fragment);
transaction.addToBackStack(null);
transaction.commit();
When I click the back button in the activity it does not return me to fragment 3 but instead rebuild the fragmentpager and start back at Fragment 2.
When you are opening fragment 3 from main fragment (fragment 2), add fragment 3 into backstack like this:
Fragment3 fragment3 = new Fragment3();
getSupportFragmentManager().beginTransaction().add(R.id.content, fragment3).addToBackStack(null).commit();
You should add all fragments to backstack that you want to return to
Ideally addToBackStack() on fragment transaction should be enough as per documentation, but it seems not true at times, so we have to handle the popping up of the back stack upon Back button pressed by ourselves. I added this to my activity and it worked as expected:
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Hope it helps.
Actually the Problem is i just load a Fragment(let call be Fragment-A) From the Navigation Drawer now the Fragment-A call a Dummy Activity, and the Dummy Activity Load a Fragment-B than fragment-B call a Fragment C and the fragment-C call the Fragment-D..
Overall Above picture:
Fragment-A(call)-->Dummy Activity(load)-->fragment-B(call)-->fragment-C(call)-->fragment-D(call)
Now i have Some Question Regarding this:
Actually there is one button in Fragment D, when the button is invoke i have to go back to the Fragment-A
now During the fragment(B,C& D) load i have to handle the On Back Pressed..
means if user in fragment D than on back press, than Fragment-C is load and vice versa but when the user is on Fragemnt-B an invoke the On-back key than Fragment A is load
NOTE :
i have to handle Both Above Back key or System Back Key
I know i have to maintain the Fragment Stack but how can i pass the case one
Edit:
Actually the Fragment-A is the Part of Activity-(a) and the remaing Fragmnets(B,C&D) is the Part of Activity-(X)
Code:
Repo link : Code link
The above scenario can be solved by below..
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
}
return super.onOptionsItemSelected(item);
}
#Override
public void onBackPressed() {
finish();
}
If the button in the fragment D invoked, please call the function
getActivity().onBackPresses();
It will finish the current Activity..
You need to add the fragments in backstack as follows:-
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.content_frame, fragmentA);
//No need to put fragment A in backstack
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.content_frame, fragmentB);
ft.addToBackStack(null);
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.content_frame, fragmentC);
ft.addToBackStack(null);
ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.content_frame, fragmentD);
ft.addToBackStack(null);
ft.commit();
Now, All your fragments are in backstack so if you press Back on fragmentD then fragmentC will be shown and on pressing Back in fragmentC, fragmentB will be shown and on pressing Back in fragmentB, fragmentA will be shown.
AS, you mentioned you have a special button in fragmentD which on pressing should take you on fragment A, So on clicking that button execute this code:-
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
I am developing an android in which when I pressed device back button I go to previous fragment. What I want to achieve is that when I pressed device back button I don't want to go to previous fragment. How can I achieve that?.
You must be doing calling addtobackstack("name") while adding or replacing the fragment.Remove this function before calling next fragment you wont go back to previous fragment for further desc
Do not add that fragment to backstack of the new fragment you're calling. Look at the below example I've used to explain you how this works.
To make that fragment come again, just add that fragment to backstack which you want to come on back pressed,
Eg:
btnSignIn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Fragment fragment = new LoginFragment();
//replacing the fragment
if (fragment != null) {
FragmentTransaction ft = ((FragmentActivity)getContext()).getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack("SignupFragment");
ft.commit();
}
}
});
In the above case, I m opening a LoginFragment when signIn button is pressed, right now am in SignupFragment. So if I call addToBackStack(TAG), TAG = "SignupFragment", then when back button is pressed in LoginFragment, we come to SignUpFragment.
Happy Coding!