Android - onCreateView is called onBackPressed - android

I have an activity with two fragments. In this one fragment is replaced by the other. I have added both fragments to the backstack.
#Override
public void showGatherIntentions() {
gatherIntentionView = GatherIntentionsFragment.newInstance(GatherIntentionContract.INTENTION_OPTION_NONE);
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (GATHER_INTENTIONS, 0);
if (!fragmentPopped) {
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(0, 0, R.anim.slide_in_right, R.anim.slide_out_right)
.replace(R.id.contentFrame, (Fragment) gatherIntentionView)
.addToBackStack(GATHER_INTENTIONS)
.commit();
currentPosition++;
}
}
code for replacing first fragment
#Override
public void showCollectPreferences() {
collectPreferencesView = CollectPreferencesFragment.newInstance(CollectPreferencesContract.DEFAULT_OPTION);
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_left,
R.anim.slide_in_right, R.anim.slide_out_right)
.replace(R.id.contentFrame, (Fragment) collectPreferencesView)
.addToBackStack(COLLECT_PREFERENCES)
.commit();
currentPosition++;
}
code for replacing the second one
#Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() == 1) {
finish();
} else {
super.onBackPressed();
currentPosition--;
}
}
State is saved for second fragment but not for first fragment i.e whenever i am on second fragment and press back button its onCreateView method is called .
Any help would be appreciated. Thanks in advance!

Related

Go back to the default fragment

I have a Android app with one activity and two fragments. First fragment (MainFragment) show a list of "items" and second (DetailsFragment) display a item's details (very basic).
On the normal flow, the activity start and show first fragment and the second is shown when a item is clicked.
But the second fragment can be shown directly throught click on a notification (by putting extra arguments to the activity).
String id = getIntent().getStringExtra("id");
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
if (id != null) {
fragment = new DetailsFragment();
Bundle args = new Bundle();
args.putString("id", id);
fragment.setArguments(args);
} else {
fragment = new MainFragment();
}
ft.replace(R.id.main, fragment);
ft.commit();
In the second case, the problem is : How to open MainFragment when clicking back from DetailsFragment ? Actually the app finish because only the second fragment has been created.
First way: Its very simple. You just need to use addToBackStack(null). It will save your desired fragment and when you use backpressed it will open that one.
Do something like this:
if (id != null) {
fragment = new DetailsFragment();
Bundle args = new Bundle();
args.putString("id", id);
fragment.setArguments(args);
ft.replace(R.id.main, fragment);
ft.commit();
} else {
fragment = new MainFragment();
ft.replace(R.id.main, fragment).addToBackStack(null);
ft.commit();
}
Second way: in your DetailsFragment's onResume() method write this code.
#Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
fragment = new MainFragment();
fragmentManager = getFragmentManager();
fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.main, fragment);
fragmentTransaction.commit();
return true;
}
return false;
}
});
}
Add the main fragment in the onCreate() of the activity and override the onBackPressed() in the main activity
FragmentTransaction mFragmentTransaction = fragmentManager.beginTransaction();
mFragmentTransaction.replace(R.id.frame_container_recharege, fragment);
mFragmentTransaction.commit();
#Override
public void onBackPressed() {
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 1) {
fragmentManager.popBackStack();
} else {
super.onBackPressed();
}
}
This is very common situation in Android, and simply saying you can just add it to backstack. So when user presses back button he will see the previous fragment(MainFragment).
getFragmentManager()
.beginTransaction()
.addToBackStack(yourFragment.getClass().getSimpleName())
.replace(R.example.container, yourFragment)
.commit();
Have a read official Android documentation about the back stack
UPDATE:
If you open DetailsFragment directly(without opening MainFragment) then you should check the back stack, if it is empty then open MainFragment manually. Here is the full code:
if (getSupportFragmentManager().getBackStackEntryCount() == 0) // empty back stack{
getFragmentManager()
.beginTransaction()
.replace(R.example.container, MainFragment)
.commit();
}
You can use something like this on your back press or back button clicked
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
fragment = new MainFragment();
ft.replace(R.id.fragment_container, frag);
ft.commit();
add fragment like this
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(containerId, fragment);
ft.addToBackStack(backStateName);
ft.commit();
and in your activity backpress put this
getSupportFragmentManager().popBackStack();

Single Instance fragment back stack managerment

I am working on single activity based principle. But I am facing a problem when the same fragment is open again because its again adds in fragment backstack entry. So backstack contains multiple backstack entries for same fragment. This creates problem on back navigation.
Example :- A|B|C|D|A|C|A
So when I press back key same fragment is displaying multiple times. Is there any way to reuse the existing fragment from backstack entry.
I am managing my backstack like this :-
fragmentManager.beginTransaction().setCustomAnimations(R.anim.fragment_enter,
R.anim.fragment_exit, R.anim.pop_enter, R.anim.pop_exit).
add(R.id.frameLayout, fragment).addToBackStack(backStateName).commit();
Any kind of help will be appreciated.
private void createOrResumeFragment(String fragmentTag){
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
boolean fragmentPopped = manager.popBackStackImmediate (fragmentTag, 0);
Fragment fragment = manager.findFragmentByTag(fragmentTag);
if(!fragmentPopped && fragment == null){
//Create an new instance if it is null and add it to stack
fragment = new MyFragment();
ft.addToBackStack(fragmentTag);
}
ft.replace(R.id.framelayout, fragment);
ft.commit();
}
Trying this using the fragment list
See the Answer Here
Initialize the fragments list
static List<String> fragments = new ArrayList<String>();
on Start of first fragment on Activity add this
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction().replace(R.id.frame, new AFragment()).commit();
fragments.add("package.fragment.AFragment");
}
Code to fragment change and take in back stack
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
//fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
if(!fragments.contains(backStateName)) {
// ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
ft.replace(R.id.frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
fragments.add(backStateName);
System.out.println("backStateName" + fragments);
}
else
{
ft.replace(R.id.frame, fragment);
ft.commit();
}
onBackpressed
#Override
public void onBackPressed() {
if(fragments.size()>0)
{
fragments.remove(fragments.size()-1);
}
super.onBackPressed();
}
for back remove stack
final android.app.FragmentManager fm = getFragmentManager();
fm.addOnBackStackChangedListener(new android.app.FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() ==0) {
// dLayout.closeDrawers();
finish();
}
else
{
// dLayout.closeDrawers();
}
}
});
Before adding or replacing the fragment on backstack, check that if the fragment already in backstack or not.
boolean fragmentPopped = fragmentManager.popBackStackImmediate(backStateName, 0);
if (fragmentPopped) {
// fragment is popped from backStack
} else {
// add or replace your fragment here
}
public void changeFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
Fragment currentVisibleFragment = fragmentManager.findFragmentById(R.id.container);
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.container, fragment, fragment.getClass().getSimpleName());
if (!currentVisibleFragment.getClass().getSimpleName().trim().equalsIgnoreCase(fragment.getClass().getSimpleName().trim())) {
for (int i = fragmentManager.getBackStackEntryCount() - 1; i > 0; i--) {
if (fragmentManager.getBackStackEntryAt(i).getName().equalsIgnoreCase(fragment.getClass().getSimpleName())) {
fragmentManager.popBackStack(fragmentManager.getBackStackEntryAt(i).getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
} else {
fragmentManager.popBackStack();
fragmentTransaction.addToBackStack(fragment.getClass().getSimpleName());
}
fragmentTransaction.commit();
}
boolean doubleBackToExitPressedOnce = false;
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
super.onBackPressed();
} else {
if (doubleBackToExitPressedOnce) {
super.onBackPressed();
finish();
return;
}
this.doubleBackToExitPressedOnce = true;
Toast.makeText(this, "Are you sure you want to exit?", Toast.LENGTH_SHORT).show();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
doubleBackToExitPressedOnce = false;
}
}, 2000);
}
}
Call the method to replace fragment with single entry in backstack
changeFragment(new YourFragmentClassName());

Android Fragments - remove fragment from back stack if already exists

I have some fragments which will be replaced by following method. I think there's something wrong with my code because I want to prevent from adding multiple times a fragment into the back stack. If I click on fragment B twice, all instances will be added to the back stack and pressing back button will be passed through the two created instances.
public void replaceFragment(Fragment fragment, boolean addToBackStack, boolean customAnimation) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
String tag = fragment.getClass().getSimpleName();
if (customAnimation) {
transaction.setCustomAnimations(R.anim.slide_in_bottom, R.anim.slide_out_bottom, R.anim.slide_in_bottom, R.anim.slide_out_bottom);
}
transaction.replace(R.id.fragment_container, fragment, tag);
// remove from back stack if exists
// always return false!
boolean f = manager.popBackStackImmediate(tag, 0);
if (addToBackStack) {
transaction.addToBackStack(tag);
}
transaction.commit();
}
Keep it simple and just add to the back stack if needed.
If the Fragment being added is the same class as the current Fragment, don't add to the back stack:
public void replaceFragment(Fragment frag) {
FragmentManager manager = getSupportFragmentManager();
if (manager != null){
FragmentTransaction t = manager.beginTransaction();
Fragment currentFrag = manager.findFragmentById(R.id.content_frame);
//Check if the new Fragment is the same
//If it is, don't add to the back stack
if (currentFrag != null && currentFrag.getClass().equals(frag.getClass())) {
t.replace(R.id.content_frame, frag).commit();
} else {
t.replace(R.id.content_frame, frag).addToBackStack(null).commit();
}
}
}
try this on your activity onBackPressed method :
#Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
if (fm.getBackStackEntryCount() > 0) {
if (fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName().equals("your fragment tag")) {
fm.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
}

Back Button on fragment not working

I have a fragment activity from where i can start my fragments which contain a viewpager. In my fragment activity I have added this piece of code.
fragment = new ItemPagerFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.content_frame, fragment);
transaction.addToBackStack(null);
transaction.commit();
Now when I press back button only blank screen appears and it does not lead me to my fragment activity.
What wrong i might be doing?
Use this in activity that holds fragment.
#Override
public void onBackPressed() {
if (fragmentManager.getBackStackEntryCount() > 1) {
fragmentManager.popBackStack();
} else
finish();
}
Try this way,
// Create new fragment and transaction
Fragment newFragment = new ItemPagerFragment();
// consider using Java coding conventions (upper first char class names!!!)
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.content_frame, newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
Modify your code
#Override
public void onBackPressed() {
if(some condition) {
// do something
} else {
super.onBackPressed();
}
}
Please follow this link
Handling back button press Inside Fragments
You have to tell to the fragment manager that the back button was pressed. Override onBackPressed on your Activity
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
private void changeFragment (Fragment fragment){
String backStackName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStackName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStackName );
ft.commit();
}
}
While launching fragment assign a TAG to each fragment.When you want to back press check the existence of an fragment using assigned TAG name and then do corresponding action.for example:
private final static String TAG_FRAGMENT = "TAG_FRAGMENT";
//when want to add fragment to view
private void showFragment() {
final Myfragment fragment = new MyFragment();
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
//in activity back pressed check the existence of fragment by TAG
#Override
public void onBackPressed() {
final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not
super.onBackPressed();
}
}

Fragment dismiss after tap on Back button

I have two Fragments - FragmentA and FragmentB.
I try to show FragmentB from FragmentA.
FragmentB fragmentB = new FragmentB();
MainActivity activity = (MainActivity) getActivity();
int fragmentContainer = activity.getFragmentContainer();
FragmentTransaction fragmentTransaction = activity.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(fragmentContainer, fragmentB);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
fragmentA = new FragmentA(getSupportFragmentManager());
//...
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(FRAGMENT_CONTAINER,fragmentA);
fragmentTransaction.commit();
}
FragmentB is showed, but when i click on back button i have a next situation - FragmentB was dismissed, but FragmentA not showed.
Why this happens and what i need to edit to get a correct result?
getActivity().getChildFragmentManager().beginTransaction();
use this it may be works inside fragmentB
Thanks to New Developer for provided link.
All that we need it's just add a
#Override
public void onBackPressed(){
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
finish();
}
else {
super.onBackPressed();
}
}
and
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
String fragmentTag = backStateName;
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(fragmentTag) == null){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment, fragmentTag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
}
}
and manage fragments in activity.
So if we need a swap fragments just call :
replaceFragment(new MySwappingFragment());

Categories

Resources