I have an activity(Activity1) with several fragments. I'm calling a second activity(Activity2) from one of the fragments(say Fragment C) of first Activity. I want to navigate back from the second activity(Activity2) to Fragment C. But, it is navigating to the first fragment of Activity1 instead of Fragment C. Please help.
Block of code I have tried so far:
In Fragment C,
categoryButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i=new Intent(getActivity(),Activity2.class);
getActivity().startActivity(i);
}
});
In the container Activity i.e Activity1,
FragmentTransaction transaction= getSupportFragmentManager().beginTransaction();
FragmentC myFragment = new FragmentC();
transaction.replace(R.id.frame_container, myFragment);
transaction.commit();
According to the Official Android Documentation the best way to have Fragment to communicate with another even to another Activity is through the associated Activity.
To avoid any mess with Fragment Transaction please referring to this:
Often you will want one Fragment to communicate with another, for
example to change the content based on a user event. All
Fragment-to-Fragment communication is done through the associated
Activity. Two Fragments should never communicate directly.
Related
Basically, I want to open a fragment from Activity. Everything worked fine (activity button opens the fragment and the fragment shows), until I miss-clicked outside the fragment's layout where one of the Activity button is located and it did its onClick method. That's why I wondered why is my Activity still active.
this is how I open the fragment from Activity
I tried using .add instead of .replace still the same.
#OnClick(R.id.login_register_lbl)
public void registerAction(View view) {
// TODO register transition...
FragmentManager fragmentManager = (LoginActivity.this.getFragmentManager());
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
RegisterFragment fragment = new RegisterFragment();
fragmentTransaction.replace(R.id.fragment_register_holder, fragment);
fragmentTransaction.commit();
}
In fragment layout in root element set "background" , "clickable=true" & Focusable="true".
In my opinion you can achieve this functionality by 2 ways:
Open a dialog fragment in full screen mode to avoid accidentally clicks on activities views.
If you wanted to show both fragment's and activity's views at the same time then, on click of your activity's button which opens the fragment, disable it by yourbutton.setenabled(false); and when you wanted to close the fragment enable that button again.
I have an Activity that creates a Fragment and then this Fragment creates another Fragment:
Activity -> Fragment1 -> Fragment2
I am now in Fragment2 and I'd like to go back to Fragment1 by clicking on a button.
In my OnClickListener of my button I have:
getActivity().getSupportFragmentManager().beginTransaction().remove(fragment2.this).commit();
This brings me to the Activity. Is there actually a way to just remove Fragment2 and go to Fragment1?
Thank you in advance for your time, I could not find any suitable info online!
#AhmedAbidi has a nice insight to your problem and yes, implementing popBackStack properly may solve your problem. But anyway, I would like to suggest a different approach to handle this type of situations.
Write two public functions in your Activity to switch between your fragments.
public void switchToFragment1() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new Fragment1()).commit();
}
public void switchToFragment2() {
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new Fragment2()).commit();
}
Now from the button click in your Fragment1 you might launch the Fragment2 via,
((YourActivity) getActivity()).switchToFragment2();
And the same thing while switching to Fragment1
((YourActivity) getActivity()).switchToFragment1();
Your question needs more code for clarity.
Is Fragment1 adding Fragment2 via getSupportFragmentManager() or getChildFragmentManager()? Presumably it appears you are doing the former, and if so, you are incorrectly using the Fragment API. Fragments are not supposed to know about each other, per Android's Fragment Documentation:
Often you will want one Fragment to communicate with another, for example to change the content based on a user event. All Fragment-to-Fragment communication is done through the associated Activity. Two Fragments should never communicate directly.
You should therefore implement the appropriate listeners to communicate from Fragment1 to Activity, which can then decide where/when to add Fragment2 -- then properly utilize the back stack functionality of getSupportFragmentManager().addToBackStack()... with getSupportFragmentManager().popBackStack(). See Android Documentation on Back Navigation for Fragments for further explanation.
In my Android Application, I have two Fragments in my Activity, A and B.
In “A” Fragment I have developed one form and in that form some data is coming from a database. I have used a fragment transaction and replaced fragment “A” with fragment “B”.
Here is my code to replace Fragment A with FragmentB.
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
FragmentB reload = new FragmentB();
fragmentTransaction.replace(android.R.id.content,reload);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
In “B” Fragment, I am fetching data from a server and storing it in an SQLite database so we can use the latest data in the application. When I click on the back button it returns back to Fragment “A” but all the data in Fragment “A” is not refreshed based on the newly-reloaded data.
Here is my code for main activity where I override onBackPressed() method:
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
getFragmentManager().popBackStack();
}
I want to refresh Fragment A's data with the latest values from the database when I hit the back button from the main activity. As much I know we cannot do back-press event in fragment B. Please correct me if I am wrong and suggest me how I can solve issue.
Does anybody know how I can achieve it?
If you want to add to back stack then you should use fragmentTransaction.add() . replace will just replace the fragment.
Also the right place to handle pop from backstack is through the use of OnBackStackChangedListener like this
getFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
#Override
public void onBackStackChanged() {
// find your fragment and do updates
}
});
A good reference Fragments onResume from back stack
When back pressed your Fragment onResume will be called so you can write refresh code in onResume
for better understanding refer below link
http://developer.android.com/guide/components/fragments.html
I am experiencing an issue where the previous fragment on my stack displays when transitioning to another fragment on low end devices.
Lets say I have three fragments on my stack; A, B and C. From fragment C I am starting fragment A, but I am seeing fragment B before fragment A loads. Is there any way to prevent this, other than using a transition which seems to do the trick.
I guess I am hoping there is some attribute that might be useful in this scenario. Here is how I am making my fragment transitions.
private void fragReplaceContentFragment(Fragment fragment, boolean withBackStack) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(contentFragmentContainer.getId(), fragment, String.valueOf(fragment.hashCode()));
if (withBackStack) {
transaction.addToBackStack(null);
}
transaction.commitAllowingStateLoss();
}
Try to replace transaction.commitAllowingStateLoss(); by transaction.commit(); and give a feedback here.
Given the application flow show in the graphic and textually described in the following.
Fragment 1 is the lowest fragment but not in the backstack by setting disallowAddToBackStack.
Fragment 2 is pushed onto the stack, using fragmentTransaction.addToBackStack().
A new instance of fragment 1 is pushed onto the stack.
The top most fragment (fragment 1) is popped from the stack.
Activity 2 becomes foreground.
Activity 1 becomes foreground.
Here is the generalized method I use to handle fragments:
private void changeContainerViewTo(int containerViewId, Fragment fragment,
Activity activity, String backStackTag) {
if (fragmentIsAlreadyPresent(containerViewId, fragment, activity)) { return; }
final FragmentTransaction fragmentTransaction =
activity.getFragmentManager().beginTransaction();
fragmentTransaction.replace(containerViewId, fragment);
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if (backStackTag == null) {
fragmentTransaction.disallowAddToBackStack();
} else {
fragmentTransaction.addToBackStack(backStackTag);
}
fragmentTransaction.commit();
}
Problem
When activity 1 resumes in the last step the lowest instance of fragment 1 also resumes. At this point in time fragment 1 returns null on getActivity().
Question
Why is a fragment which is not the top most on the stack resumed?
If resuming the fragment is correct - how should I handle a detached fragment?
When an Activity is not showing UI and then come to show UI, the FragmentManager associated is dying with all of your fragments and you need to restore its state.
As the documentation says:
There are many situations where a fragment may be mostly torn down (such as when placed on the back stack with no UI showing), but its state will not be saved until its owning activity actually needs to save its state.
In your Activity onSaveInstanceState and onRestoreInstanceState, try saving you Fragment references and then restore them with something like this:
public void onSaveInstanceState(Bundle outState){
getFragmentManager().putFragment(outState,"myfragment", myfragment);
}
public void onRetoreInstanceState(Bundle inState){
myFragment = getFragmentManager().getFragment(inState, "myfragment");
}
Try this out and have luck! :-)
I don't see how this would happen, unless (based on how you described the steps) you've misunderstood how fragmentTransaction.addToBackStack() works: it manages which transactions are placed in backstack, not fragments.
From the android docs:
By calling addToBackStack(), the replace transaction is saved to the
back stack so the user can reverse the transaction and bring back the
previous fragment by pressing the Back button.
So if your step 2 looked something like this in code:
fragmentTransaction.replace(containerViewId, fragment2);
fragmentTransaction.addToBackStack();
fragmentTransaction.commit();
and your step 3:
fragmentTransaction.disallowAddToBackStack()//or just no call to addToBackStack - you do not say
fragmentTransaction.replace(containerViewId, newfragment1);
fragmentTransaction.commit();
At this point, Fragment2 will be removed from the backstack, and your backstack consists of the two Fragment1 instances. in Step 4 you pop the top one, which means you should have the bottommost Fragment1 now at the top.
This explains why it is the resumed fragment if you return to the activity. But not, i'm afraid, why it is apparently detached from its activity.
Android OS can and will create and destroy fragments when it sees fit. This is likely happening when you launch Activity 2 and return to Activity 1. I'd verify for sure that it isn't the actively displayed fragment. What is probably happening is that you are seeing it do some of the creation steps for fragment 1 before it does the creation steps for fragment 2.
As for handling the detached fragments you should take a look at this page. The gist of it is that you should only be using the getActivity in certain fragment functions(Based on the fragment life cycle). This might mean that you have to move some of your logic to other functions.