I want to show or hide the back button of the action bar depending on the current backstack entry count. That means I want to show it when there is a fragment (or more) in the backstack, and hide when backstack is empty
getSupportActionBar().setDisplayHomeAsUpEnabled(b);
The problem is, when I start a new fragment and ask for the current backstack entry count, it's still the same like before. It refreshes after some milliseconds.
Also in the started fragment's onResume method, the replaced fragment still can not be found in backstack, backstack count is still the same.
Currently I have an AsyncTask that refreshes the button after 50 milliseconds. Working, but this can't be a good solution.
Any ideas?
Best regards
Edit:
Solution was
fragmentManager.addOnBackStackChangedListener(...)
There is no need for AsyncTask you already have a Backstack interface that triggers when a Fragment is being added or removed onBackStackChangeListener so instead of your call implement that and call getBackstackEntryCount() if its not 0 then you know what you will do
hen I start a new fragment and ask for the current backstack entry count, it's still the same like before
you need to add your transaction to the Backstack after your add() or replace() calls on your FragmentTransaction like this .addToBackstack("the identifier")
some indirect post
Hope it helps
Related
So right now I have a situation in which I have three fragments are committed in such an order:
Fragment A -> Fragment B -> Fragment C
Then, I start an Activity from Fragment C. The issue arises when I want to pop the back stack so the user is brought to Fragment B after the activity finishes. If I attempt to pop the back stack from the Activity before calling finish(), I get an IllegalStateException, saying that the action cannot be performed after onSaveInstanceState. Thus, is it even possible to make changes to the FragmentManager responsible for the fragments from the Activity?
How does this sound myrocks2? Android: how to make an activity return results to the activity which calls it?
First activity can start a second activity and expect a result. Upon getting back a result it knows second activity did its job, and now it's required to remove fragment c. (I don't know the logic of your app, but that can work)
Someone who thinks he is so smart gave you a negative vote, but I made sure to go away. There are no dumb questions.
I'm writing an app that loads user profiles and user's ratings for different places. The app uses fragments pervasively, and it's relatively easy to jump from a profile to a rated place.
As a user clicks a profile and gets to a rated place, they can click another profile on a rated place and go on and on.
The problem I'm having is memory related, when I'm looking at a ranked place and I click a profile, I switch from one Activity to the next. In both of these activities, after setContentView I load a fragment dynamically into layout space.
Now, as I shuttle between these activities, onSaveInstance state is almost always called, however since the Fragment displaying whatever was in the foreground before the activity switch, onDestroyView is not called.
What I would like is when onSaveInstanceState is called in these dynamic fragments, it to force onDestroyView to be called as well.
The only time onDestroyView seems to be called is when I add a Fragment to the back stack. When another activity comes to the foreground and this fragment is stopped, I'd like on DestroyView to be called as well.
The current workaround I want to implement is have an empty fragment with no view, and every time I call startActivity(Intent i), load this dummy fragment to destroy views and start the next activity. Then, when I come back, pop it off the back stack and restore the actual last fragment.
This however seems excessive. So, for a stopped fragment in a stopped activity with a new activity in front of it, how do I force it to destroy it's View?
First, you should not force or satisfy onDestroyView to fix your code, that's the job of the FragmentManager and the Android lifecyle # Pausing and Resuming an Activity. If you want to work with your existing code, use the other override methods onPause() or onStop().
Without posted code, I assume you're using the replace() method to display one fragment over another. This more or less forces you to manage the fragments yourself, some developers actually succeed in doing so with some struggle (look at other SO questions).
So my suggestion for you is either:
Maintain your own states, and show the proper fragments based on the state.
Use the BackStack and let the Fragment management handle the stack/states.
I want to remove a fragment from backstack and put another fragment in its place which hasn't been created yet. Below is a picture of what I want to achieve.
Is there any way to accomplish this?
EDIT:
As pointed out by #Elltz, it's not possible. So my question becomes
Is it possible to destroy the last fragment from back stack?
Can I handle the back button pressed manually to provide a different fragment than what is on the back stack?
NO! NO! NO !
want to remove a fragment from backstack and put another fragment
you can not manually re-arrange the BackstackEntry. you can only listen,observe and call it. look into PopBackstack(String name, int flags) hence the first no
and put another fragment in its place which hasn't been created yet
you mean a null Fragment ?.. you can not also assign references to null object, the second no
Is there any way to accomplish this?
A confirmation No.
EDIT
YES! YES! YES!
Is it possible to destroy the last fragment from back stack?
you can; using FragmentManager & FragmentTransaction
FragmentManager fm = FragmentActivity.getSupportFragmentManager();
fm.beginTransaction().remove(
fm.getBackStackEntryAt(fm.getBackStackEntryCount()-1););
the first yes
Can I handle the back button pressed manually to provide a different fragment than what is on the back stack?
Yes, you can, but you have to do it in your FragmentActivity or Activity so you will need some interface or your own logic around that, or
with your own logic implementing BackStackChangedListener, this is actually the interface i was talking about with logic, this listener gets notified anytime a Fragment goes or leaves the Backstack, hence the second yes
Third yes was for pampering.
Hope it helps Sir.
You cannot actually do this, but what you can do is, make these tansitions but hidden
go to fragment 3 from fragment 2
go to fragment 4 from 3.
By hidden I mean, that user does not see this happening (you can set the layout visibility as gone).
But this way, Fragment 2 will be in the stack.
To take out fragment 2 from the stack, do the following hidden operations:
go back to 1
go to 3 from 1
go to 4 from 3.
Hope this helps.
I have a DialogFragment, call it A, which presents an option that leads to a second DialogFragment, B, being displayed. B provides further options.
The functionality I require is as follows:
Making a selection in A leads to B being displayed (as stated above).
If the user hits back while B is being displayed, A should be resumed into view.
If the user makes a selection in B, then B should dismiss and A should not reappear.
In A, inside an onItemClick() handler I cause B to appear using:
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.remove(DialogFragmentA.this);
transaction.addToBackStack("transaction_label");
DialogFragmentB dialogFragment = DialogFragmentB.newInstance( ...some args here...);
dialogFragment.show(transaction, "frag_B");
I call .addToBackStack() as I understand this will cause the back key to pop and reverse the transaction. That is, replace B with A again.
So far, requirements 1 and 2 are met.
B makes use of AlertDialog.Builder. A positive button is used with listener. When that positive button is pressed, I want requirement 3 to be met. That is, B should dismiss and A should not reappear. But what actually happens is A appears again.
I am assuming here that within the implementation of AlertDialog's positive button is a call to dismiss() which causes the back stack to be popped, resulting in A appearing again. Is this the case?
What I have tried to do is, within the positive button's onClick(), is to obtain the FragmentManager and call .popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE). But this has no apparent effect; A continues to appear. Using popBackStackImmediate() has no effect either.
Is this perhaps because the event loop has already somehow committed to popping the back stack by the time the positive button listener's onClick() executes?
I'd be grateful for an explanation for what is occurring and how I can make it work as intended.
I think I have nailed it, helped by the question and answer here.
The key point is that the sequence of transactions is nothing -> A -> B. I want to pop the back stack to the point where I have nothing. Therefore, as well as calling .addToBackStack() for the A -> B transaction, I also need to call .addToBackStack() for the nothing -> A transaction. Then, all of those transactions can be popped off the back stack again to get back to the point of nothing: The first pop does B -> A, then the next pop does A -> nothing.
For both transactions I am now calling .addToBackStack("some_transaction"). In B's positive onClick(), I call manager.popBackStack("some_transaction", FragmentManager.POP_BACK_STACK_INCLUSIVE);. I might rethink the tags I'm giving to the transactions, but this is now working as I want it to.
So the basic point seems to be that, if you want it to be possible to go back to a DialogFragment but also go back to the point where that DialogFragment wasn't shown at all, you have to add the transaction that put it there in the first place onto the back stack, so you can pop back to that point.
I previously thought it would be possible to achieve what I wanted by only adding the A -> B transaction to the back stack, and then somehow completely purging (rather than popping) the back stack to prevent A appearing again once a selection had been made in B. But it seems that there is no way to actually 'purge' the back stack; you can only pop and reverse the transactions.
I'm trying to create a fragment that exists for the entire duration of my app's lifecycle. I want it to be created only once and to be destroyed when the activity's onDestroy() function is called (so, ideally, never...). I understand that this goes against what android intended when it introduced fragments, but the nature of my project makes changing this requirement impossible.
What I would like clarification on, is this whole backstack business. I am slightly confused about what exactly the backstack represents, I understand that it is a stack of previous UI states, but does that mean it is a stack of the fragments that the user has currently iterated through? Or is this a stack of FragmentTransactions and when you popBackStack(), it "undo's" the last FragmentTransaction that was committed (and if so, what does it mean to "undo" a FragmentTransaction...does it just remove an added fragment and add a removed fragment, what if I want it to detach a fragment and not remove it when popBackStack() is called?)?
Finally, does calling detach() prevent Android from killing my Fragment (unlike remove() and replace() which will immediately call the onPause(), onStop(), onDestroy(), onDestroyView() sequence)? If so, how do I get popBackStack() to detach() my Fragment (can I even do this?)...should even be adding it to the backstack?
Further restraints on my project - I want all other fragments to behave normally (i.e. they should be able to be destroyed/created at will by the OS). This fragment will not open another fragment, but if I hit the back button, I want it to return to whatever fragment opened it (without destroying the fragment).
Any guidance and/or clarification on the issues I enumerated above would be greatly appreciated!! Thanks in advance!