I have a problem implementing the back navigation.
Activity A1 starts Activity A2. A2 contains a full screen fragment:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- fragment goes here -->
</RelativeLayout>
in A2's onCreate() I load the fragment F1 in the container above:
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.activity_main);
replaceFragment(new AccountHomeFragment());
}
public void replaceFragment(Fragment f){
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, f);
fragmentTransaction.addToBackStack(f.getClass().getSimpleName());
fragmentTransaction.commit();
}
And at some point the user clicks on a button and the F1 is replaced by F2. The problem is when the user clicks on the back button:
1st click: nothing happens
2nd click: goes from F2 to A1 (F1 skipped)
What I expect
1st click: F2->F1
2nd click: F1->A1
I have noticed that if I press back before F1 is replaced by F2:
1st click: F1->blank screen
2nd click: blank screen->A1
I think your problem may be caused by adding your first fragment to the backstack as well. In your onCreate you call replaceFragment which adds it automatically. Just add the fragment manually without the addToBackStack call and use the replaceFragment function for all subsequent fragment transactions.
Related
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.
I have fragments in stack like Main frag --> A frag --> B frag --> C frag --> D frag.
How can I go back to main fragment from any of A, B, C, D fragment. For eg: if i clicked button in D, I should be back to Main fragment. Same should happen in case of button click on fragment C. And, on back button click from Main fragment, it should not go back to Fragment D or C.
I tried to pop out all fragment from stack & start again from main fragment. But it doesn't work.
private void onButtonClick(){
MainFragment mainFrag= new MainFragment();
getActivity().getSupportFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);//pop back stack inclusive pops all fragment
getActivity().getSupportFragmentManager().beginTransaction().add(R.id.mainFragment, mainFragment).addToBackStack(null).commit();
}
Edit : Ok, it looks like above code is going back to main fragment. But after showing Main fragment for a second, the app minimizes. After main fragment minimizes, following log is shown on Android logcat.
V/FA: Screen exposed for less than 1000 ms. Event not sent. time: 570
V/FA: Activity paused, time: 14995077
V/FA: Inactivity, disconnecting from the service
If MainActivity is your frameLayout place , here is my answer:
//just add a switch method on your activity
public void switchFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.mainFrame, fragment, null);
transaction.addToBackStack(null);
transaction.commit();
}
and use it in any fragments for your button like this:
private void onButtonClick(){
(MainActivity)getActivity()).switchFragment(new the fragment));
}
Hope it can help~
getSupportFragmentManager().popBackStackImmediate(mainFragment.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
I have an app in which I swap two fragments. The fragments are in a LinearLayout. Below the linearlayout I have icons (ImageViews) that when clicked hides or shows the appropriate fragment. When the app first loads, everything is fine. After I exit my app and use another app then return to my app the fragments dont hide/show when I click the icons (ImageView). WHy is this happening? Does it have something to do with the activity life cycles?
xml_layout:
<LinearLayout
android:id="#+id/Linearlayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</LinearLayout>
onCreate()
{
ft = this.getSupportFragmentManager()
.beginTransaction();
frag1= new Frag1();
frag2= new Frag2();
ft.add(R.id.linearlayout,frag1);
ft.add(R.id.linearlayout, frag2);
ft.hide(frag1).show(frag2);
ft.commit();
icon1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ftt = MainActivity.this.getSupportFragmentManager()
.beginTransaction();
ftt.hide(frag2).show(frag1);
ftt.commit();
}
});
}
I think your problem is in this line:
ft.hide(frag2).show(frag2);
You want to hide frag1 and show frag2:
ft.hide(frag1).show(frag2);
Yes, the answer relates to the activity cycle. You need to override onCreateView and put your onClickListener inside of that. The onCreate is only getting called when the activity is first created. OnCreateView is called immediately after that, but it is also called when your activity is brought back to the front after you return from another activity.
I have one activity and multiple fragments in my app. i want to back one by one fragments when pressing back button which in all fragments.
i used this code segment but when pressing back button it comes to main activity without back one by one. Also i want to change the icon when it's comes to the main activity.(msg_alert)
btnBack.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
FragmentManager fm = MainActivity.this
.getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
Fragment fragment = new MainMenuLayout();
ft.replace(R.id.activity_main_content_fragment, fragment);
ft.commit();
btnBack.setVisibility(View.VISIBLE);
btnBack.setImageResource(R.drawable.msg_alert);
tvTitle.setText("Layout 0");
}
});
Lets say you are having two fragments A and B. Fragment A is is attached at the startup of activity and on any user event you navigate to fragment B by replacing the Fragment A.
1) while adding Fragment B to the activity
// Works with either the framework FragmentManager or the
// support package FragmentManager (getSupportFragmentManager).
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragmentB, "detail")
// Add this transaction to the back stack
.addToBackStack()
.commit();
2) override the onBackPressed of the activity to handle the back button press event.
#override
public void onBackPressed() {
// is there any fragment in backstack, if yes popout.
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
getSupportFragmentManager().popBackStack();
return;
}
super.onBackPressed();
}
this is one more option ,
in the Activity.
Fragment secondfragment= new SecondFragmnet();
#Override
public void onBackPressed() {
if(secondfragment.isVisible()){
// replace 1st fragment
}else{
// Alert dialog for Exit App
}
// you can check multiple fragments.
Hope it helps you
You have to Use addToBackStack() method while doing Transaction Between Fragments...
Read This : Implement Back Navigation for Fragments
Use Following code when you use Fragment Transaction...
String backStateName = fragment.getClass().getName(); // getting Fragment Name..
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment)
.addToBackStack(backStateName) //adding it to BackStack..
.commit();
In Fragments we dont have back navigation..
We can acheive that through replace() method.
I seen in your code that you are only replace the content frame. and so the result is backpress it comes to activity.
Also be sure that you have your mannual back button in the activity
this is test xml for activity
<?xml version="1.0" encoding="utf-8"?>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Back" />
<FrameLayout
android:id="#+id/activity_main_content_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>
Use
Fragment fragment = new MainMenuLayout();
ft.replace(R.id.activity_main_content_fragment, fragment);
ft.addToBackStack(null);// TODO parameter here it tag of fragment or null or "" String
ft.commit();
For more information about fragments backstack go through this android developer refrence :-Fragment BackStack
In my app, I have only one Activity which hosts several fragments.
The layout of my activity is(main.xml):
<LinearLayout...>
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/fragment_placeholder">
</FrameLayout>
</LinearLayout>
My only Activity:
public class MyActivity extends FragmentActivity{
...
#Override
protected void onCreate(Bundle arg0) {
super.onCreate(arg0);
setContentView(R.layout.main);
//I dynamically add fragments into fragment_placeholder of the layout
FirstFragment firstFragment = new FirstFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_placeholder, FirstFragment, "first");
fragmentTransaction.commit();
}
}
I my above activity, I dynamically add the first fragment to layout. The other fragments replace this fragment accordingly.
I know when user press back button to exit the app, by default, my app will still run on background.
what I want however is to kill the app process when user seeing the firstFragment and press the back button (exits the app). But how can I kill my app technically(programmatically) in Android?
I end up killing my app process by:
android.os.Process.killProcess(android.os.Process.myPid())
you can override the back button behaviour by using below code and kill your activity
public void onBackPresed(){
finish();
}