I have multiple fragments and I can switch between them, my problem is on how can I execute a method in a fragment before it goes to backstack.
If I execute some method in fragment's OnPause() or OnStop() my activity is closing with all fragments instantly. The code to switch from one fragment to another is:
public void switchFrgFromFrg(Fragment fragment, String tag, boolean isAddedToBackStack, int idContainer) {
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(idContainer, fragment, tag);
if (isAddedToBackStack) {
fragmentTransaction.addToBackStack(tag);
}
fragmentTransaction.commit();
}
Any help is apreciated.
Your fragment onResume() and onPause() will be called only when the Activity onResume() or onPause() that holds it is called. They are tightly coupled to the Activity, that's why your fragment is closing. I sugest you ti implement a back key listener as:
private void doBackActionListener(View view){
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
//execute code
//then do standart go back action
getActivity().onBackPressed();
return true;
}
}
return false;
}
});
}
You will cal this in your onCreateView() and pass inflated view as parameter.
how can I execute a method in a fragment before it goes to backstack
When you fragment is visible you can execute as many methods as you want
If I execute some method in fragment's OnPause() or OnStop() my activity is closing with all fragments instantly.
That's because some Exception is arising in your code. It is better to show your console (Log messages) in your question.
Related
I am trying to implement back navigation through my fragments which are called in specific order: A->B->C and by going back with hardware button I would like them to remain order.
I am using fragmenttransaction.replace in order to switch fragment with no addToBackStack because it made my ActionBarMenu to misbehave.
Problem is that when I am on fragment C back button is going back directly to A. I found out that it is because click event is executed twice I am going to B and directly to A.
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setOnBackButtonPresed();
}
private void setOnBackButtonPresed() {
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener( new View.OnKeyListener()
{
#Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
goBackToDays();
return false;
}
return false;
}
} );
}
private void goBackToDays() {
Log.e("fragmentC", "executing on back action")
}
logcat result:
03-15 08:37:17.353 21245-21245/com.test E/fragmentC: executing on back action
03-15 08:37:17.390 21245-21245/com.test E/fragmentC: executing on back action
Can anyone give me a hint how I can avoide twice button events?
I think "click event is executed twice" because you call both event ACTION_DOWN and ACTION_UP. Try this
#Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction()== KeyEvent.ACTION_DOWN)
{
goBackToDays();
return false;
}
return false;
}
2 things:
Even though you're replacing fragments, the old OnKeyListener stays there (and get's fired up later on). Try removing the old OnKeyListener on switching fragments.
Just as S-lightning pointed out, you need to bare in mind that there are two actions associated with a key event (KeyEvent.ACTION_DOWN and KeyEvent.ACTION_UP).
You can do two things
"it made my ActionBarMenu to misbehave." FIX this issue.
Override onBackPressed() on your Activity and find find out your current loaded fragment and replace with whichever you want.
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.your_view_container);
if (fragment instanceof FragmentThree) {
//replace with your fragment ie. FragmentTwo
} else if (fragment instanceof FragmentTwo) {
//replace with your fragment ie. FragmentOne
}
Return true if you want to "absorb" the key event and stop it from propagating up to the Activity, which has its own onBackPressed() implementation.
if( keyCode == KeyEvent.KEYCODE_BACK )
{
goBackToDays();
return true; // <-- should be TRUE, not FALSE
}
return false;
Override the onBackPressed() method in hosting activity.
do like this.
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);
if (!fragmentPopped){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.addToBackStack(backStateName);
ft.commit();
}
}
.
.
#Override
public void onBackPressed(){
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
finish();
}
else {
super.onBackPressed();
}
}
Here is the well explained answer. link
I create sample app to show some data to user when user start specific activity and click on specific button the app start new fragment (only fragment added to activity for now ) my problem is when user click back the fragment and the activity removed and go to parent activity. using this code to do that
android.support.v4.app.FragmentManager fragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
fragmentManager.popBackStack();
also I use the same code in another action when user click in specific button fragment and back correctly.
Can anyone help me to solve that
Add fragments to back stack when create them and override onBackPressed in your activity.
To add fragment
FragmentManager mFragmentManager = ((FragmentActivity) context).getSupportFragmentManager();
FragmentTransaction ft = mFragmentManager.beginTransaction();
ft.addToBackStack("tag of fragment");
ft.add("your container id", fragment);
ft.commit();
onBackPress
#Override
public void onBackPressed() {
if (mFragmentManager.getBackStackEntryCount() > 0)
mFragmentManager.popBackStackImmediate();
else super.onBackPressed();
}
To remove only fragment you have to add that fragment in addToBackStack(TAG) so that when you press back it popout only Fragment which are added to stack
override onBackPressed() and remove fragment. Back stack for fragments works differently as it stores transaction not fragments. So can not pop back a fragment but a transaction
This is work for me to handle backpressin a fragment in a fragment to remove backstack.
#Override
public void onResume() {
super.onResume();
if (getView() == null) {
return;
}
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
if (keyEvent.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
Toast.makeText(getActivity(), "Clicked Back", Toast.LENGTH_SHORT).show();
getActivity().finish();
return true;
}
return false;
}
});
}
if I launch a full-screen dialog like such
FragmentManager fragmentManager = getActivity().getFragmentManager();
DialogStyleCreator editor = new DialogStyleCreator();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.add(android.R.id.content, editor).commit();
How can I make it so that if I hit the android back arrow (in the top left of the menu) or the back button it closes the dialog instead of going back to the previous activity like in alert dialogs?
You may simply put your transaction in stack of fragment manager and override the function of back button
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (Integer.parseInt(android.os.Build.VERSION.SDK) > 5
&& keyCode == KeyEvent.KEYCODE_BACK
&& event.getRepeatCount() == 0) {
// Simply pop back your fragment stack here
return true;
}
return super.onKeyDown(keyCode, event);
}
#Override
public void onBackPressed() {
// Simply pop back your fragment stack here
}
Since you have added the DialogFragment as transaction.add(android.R.id.content, editor).commit(); you may not have option to listen the dismiss call back.
I suggest you to create the DialogFragment instance and start it like
fm.beginTransaction().add(sampleDialog, "Dialog").commit();
and set the call back interface for Activity Back Button Click and call dismiss();
which function will be called after popBackStack is called?
I mean, when a certain fragment becomes active after calling popBackStack, which function will be called?
I did debug but onResume is called after certain activity is done something like clicking button etc.
But I need to call a function when fragment becomes active by getting called popBackStack
I just had the same question and tried to find out which default method is called when a fragment becomes active after calling popBackStack, but couldn't find any default methods called(here I mean onResume, onAttached, etc by default methods).
Hence I worked it out by calling the active fragment's method explicitly just after calling popBackStack.
For example, suppose we have two fragments A and B in the same activity and have clicked back button of the Android device on fragment A.
//fragment A
#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) {
// handle back button
FragmentManager fm = getFragmentManager();
fm.popBackStack();
//call fragment B.setBackButtonLister method
B fragment = (B)getFragmentManager().findFragmentByTag(B.TAG);
if (fragment != null){
fragment.setBackButtonListener();
}
return true;
}
return false;
}
});
}
This way, you can call any method of fragment B after you get the handle of B.
Hope this will help you, Cheers!
I want to go back to the last fragment in the back stack, so I want to make the back button popback the stack. Should I do this? and if so, should I override onBackPressed() or onKeyDown()?
#Override
public void onBackPressed()
{
Intent intent = new Intent(this,ABC.class);
startActivity(intent);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK ) {
// do something on back.
return true;
}
return super.onKeyDown(keyCode, event);
}
My fragments aren't being added to the back stack properly for some reason
I am using this to try to go back to the previous fragment, but the order is acting strange. What exactly should I do to make the order proper?
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft){
if(teamsFrag !=null)
{
if(manage.getBackStackEntryCount() > 0)
manage.popBackStack(manage.getBackStackEntryAt(manage.getBackStackEntryCount()-1).getName(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
//ft.detach(dataFrag);
}
Short answer? No.
Long answer? If you have to ask, No.
You should set your fragments up using the fragment manager so that the back button does what you want. You shouldn't override the back button instead of implementing your stack correctly.
I want to go back to the last fragment in the back stack, so I want to make the back button popback the stack.
This is the default behavior when you use FragmentTransaction#addToBackStack() while adding new Fragments with the FragmentManager.