addToBackStack Not working - android

I am trying to close the fragment and wants to resume the main activity by using the addToBackStack in my fragment implimentation but it is not working. Back button is closing the application.
The fragment implimentation method that I am using is,
private void dispaySelectedScreen(int id) {
Fragment fragment = null;
switch (id) {
case R.id.facebook_login:
fragment = new FacebookLogin();
break;
case R.id.memes:
fragment = new Memes();
break;
case R.id.submit_image:
fragment = new SubmitImage();
break;
case R.id.discussion:
fragment = new Discussions();
break;
case R.id.invite:
fragment = new Invite();
break;
case R.id.connect_fb:
fragment = new FacebookConnect();
break;
case R.id.connect_twitter:
fragment = new TwitterConnect();
break;
case R.id.connect_instagram:
fragment = new InstaConnect();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_main, fragment);
ft.addToBackStack(null);
ft.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
I have also declared one onBackPressed method for the drawer,
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
Please suggest..

fragment.addToBackStack(null) is enough to open the previous activity but if you want to handle some action on back pressed apart from removing the fragment then we override onBackPressed(), so this is my tested approach, kindly have a look:-
Below is my implementation:-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_holder, new MyFragment(), "MY_FRAG")
.addToBackStack(null).commit();
}
#Override
public void onBackPressed() {
MyFragment fragment = (MyFragment) getSupportFragmentManager().findFragmentByTag("MY_FRAG");
if (fragment != null) {
if (fragment.isVisible()) {
//todo perform any action if you want when fragment is removed
}
} else {
super.onBackPressed();
}
}

I see you are using replace on transaction in that way your fragment will pop up from stack but it will reload i.e onCreateView() of that fragment will be called . Just replace
ft.replace(R.id.content_main, fragment);
to
ft.add(R.id.content_main, fragment);
For handling back button use following code .
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
//that means your stack is empty and you want to close activity
finish();
} else {
// pop the backstack here
getSupportFragmentManager().popBackStackImmediate();
}
}
}

Related

fragment back goes to specified fragment

I am developing an android app using fragments. I have five fragments. Those are A,B,C,D,E . My first fragment A is the main fragment. First I traverse from A to B then from B to C. In C when I press back button I want it to go back to A. I have used the below code for calling B fragment from A. This same method is used for calling another fragments.
FragmentB fragment = new FragmentB();
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction().addToBackStack("tag");
transaction.replace(R.id.content_frame, fragment);
transaction.commit();
The back button code in the activity is as following
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
How to solve this issue please help me.
You can try this:
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} FragmentManager fragmentManager = getSupportFragmentManager();
int backCount = fragmentManager.getBackStackEntryCount();
System.out.println("back count " + backCount);
if(backCount==0)
{
actionBar.setTitle("Home");
//Here you can show alert dialog for exit the app?
}
/* else if(backCount==1)
{
}*/
else if(backCount==1)
{
fragmentManager.popBackStack();
// setTitle("Home");
navigationView.getMenu().getItem(0).setChecked(true);
actionBar.setTitle("Home");
}
else if(backCount>1)
{
for(int i=fragmentManager.getBackStackEntryCount();i>=1;i--)
{
fragmentManager.popBackStack();
System.out.println("back count loop" + fragmentManager.getBackStackEntryCount());
}
actionBar.setTitle("Home");
}
}
Try this:
#Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawers();
return;
}
// This code loads home fragment when back key is pressed
// when user is in other fragment than home
if (shouldLoadHomeFragOnBackPress) {
// checking if user is on other navigation menu
// rather than home
if (navItemIndex != 0) {
navItemIndex = 0;
CURRENT_TAG = TAG_HOME;
loadHomeFragment();
return;
}
}
super.onBackPressed();
}
Refer this reference : https://www.androidhive.info/2013/11/android-sliding-menu-using-navigation-drawer/

How to handle onBackPressed() in multiple fragment

I am Android beginner, I am developing an app in which I have used multiple fragments through an activity.
private void displaySelectedScreen(int itemId) {
Fragment fragment = null;
switch (itemId) {
case R.id.nav_home:
fragment = new HomeFragment();
break;
case R.id.nav_attendance:
fragment = new AttendanceFragment();
break;
case R.id.nav_notification:
fragment = new NotificationFragment();
break;
case R.id.nav_event:
fragment = new EventFragment();
break;
case R.id.nav_fee:
fragment = new FeesFragment();
break;
case R.id.nav_news:
fragment = new NewsFragment();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.frame_container, fragment);
ft.addToBackStack(null);
ft.commit();
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
}
and use an onBackPressed() method to close an app if the drawer is already close. Now I want to close an app if current fragment is HomeFragment and if current fragment is not HomeFragment then replace by HomeFragment. I don't know, how it does?
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
closeApp();
}
}
You can add tag to your fragment. in this way you will only have to check the tag name.
Fragment fragment = new Fragment();
getFragmentManager().beginTransaction()
.replace(R.id.FrameLayoutId,fragment,"TAG_NAME")
.addToBackStack("SOURCE_TAG_NAME").commit();
This is how to check your fragment tag, put this checking on your backpress method on the activity or in your closeApp() method
function void closeApp(){
Fragment fragment = getFragmentManager().findFragmentByTag("HomeActivity");
if (fragment != null) {
if(fragment.isVisible()){
HomeActivity.this.finish();
}
}
}
Use this code onBackPressed() method in NavigationActivity. I hope that can solve you.
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
Fragment f = getVisibleFragment();// to get which fragment now
if (f.getClass() != MainFragment.class) {
Fragment fragment = null;
try {
fragment = (Fragment) MainFragment.class.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame, fragment).commit(); // this is your framelayout
}else {
super.onBackPressed();
}
}
}
getVisibleFragment() function
public Fragment getVisibleFragment() {
FragmentManager fragmentManager = NavigationActivity.this.getSupportFragmentManager();
List<Fragment> fragments = fragmentManager.getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null && fragment.isVisible())
return fragment;
}
}
return null;
}
For simple, just go to your HomeFragment.java and edit the method onBackPressed() to exit the application using finish().
And for others Fragment.java, just use popBackStack() function, you can search for it here :
https://developer.android.com/reference/android/app/FragmentManager.html#popBackStack()
In your MainActivity class override onBackPressed and display dialogbox there like this:
#Override
public void onBackPressed() {
//show dialog box here
}
In each Fragment implement onResume() method with following 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){
//homefragment class name
Class fragmentClass = HomeFragment.class;
try {
Fragment fragment = (Fragment) fragmentClass.newInstance();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
fragmentManager.beginTransaction().replace(R.id.flContent, fragment).commit();
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
return false;
}
});
}

addToBackStack not working with onBackPressed method

I have created a tabbed activity inside a navigation drawer activity. I have linked the lists inside the navigation drawer with individual fragments. I also used the command ft.addToBackStack(null) before ft.commit(). It was perfectly fine and I was able to use it to close the fragments inside the navigation drawer. now I have created webviews inside the fragments of the tabbed activity (home page). I added the onBackPressed to go back inside the webview and now the addToBackStack method stopped working.
For the navigation drawer fragments,
private void dispaySelectedScreen(int id) {
Fragment fragment = null;
switch (id) {
case R.id.fragment1:
fragment = new Fragment1();
break;
case R.id.fragment2:
fragment = new Fragment2();
break;
case R.id.fragment3:
fragment = new Fragment3();
break;
case R.id.fragment4:
fragment = new fragment4();
break;
}
if (fragment != null) {
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_main, fragment);
ft.addToBackStack(null);
ft.commit();
}
onBackPressed Method
#Override
public void onBackPressed() {
if (hWebView.canGoBack()) {
hWebView.goBack();
} else if (!getFragmentManager().popBackStackImmediate())
if (sWebView.canGoBack()) {
sWebView.goBack();
} else if (!getFragmentManager().popBackStackImmediate())
if (dWebView.canGoBack()) {
dWebView.goBack();
} else if (!getFragmentManager().popBackStackImmediate());
}
Please help me out!!!
try this code: override onBackPressed() in your tabbed activity (home page).
#Override
public void onBackPressed() {
FragmentManager fm = getSupportFragmentManager();
if (hWebView.canGoBack()) {
hWebView.goBack();
} else if (!getFragmentManager().popBackStackImmediate())
if (fm.getBackStackEntryCount() > 0) {
fm.popBackStack();
} else {
super.onBackPressed();
}
}

Android NavigationView change title onBackPressed

I have a NavigationView that changes certain Fragment by clicking on its item and setting toolbar's title with item's name:
fragmentTransaction = getFragmentManager().beginTransaction();
int id = item.getItemId();
switch (id){
case R.id.studying:
fragmentTransaction.replace(R.id.container, studyFragment).addToBackStack(null);
break;
case R.id.events:
fragmentTransaction.replace(R.id.container, eventsFragment).addToBackStack(null);
break;
case R.id.discount:
fragmentTransaction.replace(R.id.container, discountsFragment).addToBackStack(null);
break;
case R.id.bookmarks:
fragmentTransaction.replace(R.id.container, bookmarksFragment).addToBackStack(null);
break;
case R.id.settings:
fragmentTransaction.replace(R.id.container, settingsFragment).addToBackStack(null);
break;
case R.id.prolong_sign:
fragmentTransaction.replace(R.id.container, prolongFragment).addToBackStack(null);
break;
case R.id.contacts:
fragmentTransaction.replace(R.id.container, contactsFragment).addToBackStack(null);
break;
}
toolbarTitle.setText(item.getTitle().toString());
fragmentTransaction.commit();
Proving better usability I override onBackPressed method:
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
FragmentManager fm = getFragmentManager();
if (fm.getBackStackEntryCount() > 0 && fm.getBackStackEntryCount() != 1) {
fm.popBackStackImmediate();
} else if (fm.getBackStackEntryCount() == 1) {
toolbarTitle.setText("TEST");
fm.popBackStackImmediate();
} else {
super.onBackPressed();
}
}
}
If I back to the first Fragment, my toolbarTitle sets okay according to:
else if (fm.getBackStackEntryCount() == 1) {
toolbarTitle.setText("TEST");
fm.popBackStackImmediate();
}
But I don't know how to make toolbarTitle to change title correctly on each onBackPressed and make previous item in NavigationView checked. Can you help me with it?
EDIT
I created an interface
public interface OnToolbarTitle {
void setTitle(String title);
}
implemented it MainActivity and overrided
#Override
public void setTitle(String title) {
toolbarTitle.setText(title);
}
And tried to use it in Fragments by attaching it in Fragments:
#Override
public void onAttach(Context context) {
super.onAttach(context);
titleSetter = (OnToolbarTitle) context;
}
#Override
public void onResume() {
super.onResume();
titleSetter.setTitle("Test-frag3");
}
But I got NullPointerException in line with setTitle() method.
EDIT
Ok I solved my problem by accessing Toolbar in fragment.
View view = getActivity().findViewById(R.id.toolbar);
TextView title = (TextView) view.findViewById(R.id.toolbar_title);
title.setText("study lol");
Still, I'd be glad to see, how can I achive it with interface.
You should consider making your fragments setting the title. I.e. define interface like:
interface HostContract {
setTitle(String title);
}
and make your activity implement it. Then in each fragment you should call ((HostContract)getActivity).setTitle() in fragment's onResume(). This way you set the title when your fragment goes into game (be it because it is newly added, or because you took previous one from backstack, which should solve your problem. And that's basically all you need to do.
your if...else should be like
if (fm.getBackStackEntryCount() > 0 && fm.getBackStackEntryCount() != 1) {
fm.popBackStackImmediate();
toolbarTitle.setText("TEST");
} else if (fm.getBackStackEntryCount() == 1) {
toolbarTitle.setText("TEST");
fm.popBackStackImmediate();
} else {
super.onBackPressed();
}

onBack pressed in activity and fragment

Navigation drawer with fragments. I have placed one fragment on main activity. But if i back press the same fragment comes again. How can I handle this??
and secondly how to implement onBackpressed in fragments??
Can anybody help me out?
in onCreate of main activity I have
FragmentTransaction tx = getFragmentManager().beginTransaction();
tx.replace(R.id.mainFrame, new PlaceOrderFragment());
tx.commit();
and in back press of it I have
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
First you need to add the fragmnet to back stack so we could retrieve it later in onBackPressed()
Replace your fragmnet transaction with this
FragmentTransaction tx = getFragmentManager().beginTransaction();
tx.replace(R.id.mainFrame, new PlaceOrderFragment());
// HERE WE WILL ADD FRAGMENT TO BACKSTACK SO WE COULD GET BACK TO IT
tx.addToBackStack(null);
tx.commit();
Replace your onBackPressed with this
#Override
public void onBackPressed() {
// CHECKS HOW MANY FRAGMENTS ARE IN THE BACKSTACK
int count = getFragmentManager().getBackStackEntryCount();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
if (count == 0) {
// IF NO FRAGMENT IN THE BACKSTACK CALL
super.onBackPressed();
} else {
// GET THE LAST OPENED FRAGMENT
getFragmentManager().popBackStack();
}
}
}
You can do this using Interface. That interface will implemented in each fragment. Here is a simple example:
public interface OnBackPressedListener {
void onBackPressed();
}
Here, if you implement this interface in your fragment then you will found this method:
#Override
public void onBackPressed() {
getActivity().finish(); // Or Do your specific task
}
Now your Activity that holds that fragment , that should use onBackPressed() callback. Write bellow code in that method
#Override
public void onBackPressed() {
if (YOUR_DRAWER.isDrawerOpen(GravityCompat.START)) {
YOUR_DRAWER.closeDrawer(Gravity.LEFT); //CLOSE Nav Drawer!
return;
}
Fragment fragment=getYourVisibleFragment();
if(fragment!=null){
((OnBackPressedListener)fragment).onBackPressed();
}else{
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
If you want to get Visible fragment then just use this method
public <F extends Fragment> F getVisibleFragment() {
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null && fragment.isVisible()) {
return (F) fragment;
}
}
}
return null;
}
That's it :)
FragmentTransaction tx = getFragmentManager().beginTransaction();
tx.replace(R.id.mainFrame, new PlaceOrderFragment()).addToBackStack("your tag");
tx.commit();
Override onBackPress() and try following code.
#Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//your other utility code if needed
} else {
getFragmentManager().popBackStack();
}
}
Hope this will work for you.
Replace ypu fragment in onCreate with fragment id , and then implement onBackpressed on the same activity and find that fragment with id and check is it visible or null and then perform operations based on it.
hope you got this.

Categories

Resources