Search code examples
androidandroid-fragmentsandroid-actionbarandroid-tabsback-stack

backstack in fragments not working


In My MainActivity, I am adding three tabs named FragmentA, FragmentB and FragmentC.

In FragmentA tab, i am populating a list of contacts via list fragment and adding this fragment to backstack. Now when i click on any of list item, it displays the detailed fragment of that contact under the same tab FragmentA. When i press the back button, it goes back to list fragment of contact list.

On detail fragment, rather than clicking on back button, when i click on FragmentB tab , it is supposed to display a simple text, which is working fine. But When i click on back button now, it is supposed to close the application, but it goes back to list fragment, but remains inside of FragmentB tab, hence merges the both fragments.

In my MainActivity.java,

@Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {

if(tab.getPosition() == 0){
    PM_Fragment pm_Fragment= new PM_Fragment();
    FragmentManager manager= getFragmentManager();
    FragmentTransaction frgTrans = manager.beginTransaction();
    frgTrans.replace(android.R.id.content, pm_Fragment);
    frgTrans.commit();
}

else    if(tab.getPosition() == 1){
    TabFragmentTwo tabFragmentTwo= new TabFragmentTwo();
    Bundle bundle = new Bundle();
    bundle.putString("Fragment", "2nd Fragment");

    tabFragmentTwo.setArguments(bundle);
    FragmentManager manager= getFragmentManager();
    FragmentTransaction frgTrans = manager.beginTransaction();
    frgTrans.replace(android.R.id.content, tabFragmentTwo);
    frgTrans.commit();
}

else {
    TabFragmentThree tabFragmentThree= new TabFragmentThree();
    Bundle bundle = new Bundle();

    bundle.putString("Fragment", "3rd Fragment");

    tabFragmentThree.setArguments(bundle);
    FragmentManager manager= getFragmentManager();
    FragmentTransaction frgTrans = manager.beginTransaction();
    frgTrans.replace(android.R.id.content, tabFragmentThree);
    frgTrans.commit();
    }

}

PM_Fragment.java displaying the contacts list.

package com.android.myactiobartabs;
import android.app.ActionBar;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.SimpleCursorAdapter;
import android.widget.Toast;

public class PM_Fragment extends ListFragment 
                        implements OnQueryTextListener , LoaderManager.LoaderCallbacks<Cursor>{
    String mCurFilter;
    SimpleCursorAdapter mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);

        ActionBar actionBar = getActivity().getActionBar();
//      actionBar.setDisplayHomeAsUpEnabled(false);
        MenuButtonUtil.enableMenuButton(getActivity());

    }
    @Override
    public View onCreateView(LayoutInflater inflater,ViewGroup container, Bundle savedInstanceState) {

        View rootView = inflater.inflate(R.layout.activity_list_view_with_simple_adapter, container,false);

        mAdapter = new SimpleCursorAdapter(getActivity(),
                R.layout.pm_fragment, null,
                new String[] {ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER},
                new int[] { R.id.textView1, R.id.textView2 }, 0);
        setListAdapter(mAdapter);

        getLoaderManager().initLoader(0, null, this);

        return rootView;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

        inflater.inflate(R.menu.pm_fragment_actionitems, menu);
        MenuItem searchItem = menu.findItem(R.id.pm_action_search);
        SearchView sv = new SearchView(getActivity());
    // Changing the color of Searchview widget text field to white.     
        int searchSrcTextId = getResources().getIdentifier("android:id/search_src_text", null, null);  
        EditText searchEditText = (EditText) sv.findViewById(searchSrcTextId);  
        searchEditText.setTextColor(Color.WHITE); 

        sv.setOnQueryTextListener(this);
        searchItem.setActionView(sv);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
        case R.id.pm_action_delete:
            Toast.makeText(getActivity(),"Text_DELETE!",Toast.LENGTH_SHORT).show();
            return true;
        case R.id.pm_action_edit:
            Toast.makeText(getActivity(),"Text_EDIT!",Toast.LENGTH_SHORT).show();
            return true;
        case R.id.pm_action_add_person:
            final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
            startActivity(intent);
            return true;
        case R.id.pm_action_refresh:
            Toast.makeText(getActivity(),"Text_REFRESH!",Toast.LENGTH_SHORT).show();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {

        getListView().setItemChecked(position, true);

        DetailsFragment detailsFragment = new DetailsFragment();

        Cursor mycursor = (Cursor) getListView().getItemAtPosition(position);
        System.out.println("mycursor.getString(1) " + mycursor.getString(2) +"   ");

        Bundle bundle = new Bundle();
        bundle.putString("CONTACT_NAME",  mycursor.getString(1));
        bundle.putString("CONTACT_NUMBER",  mycursor.getString(2));

        detailsFragment.setArguments(bundle);
        FragmentManager manager= getActivity().getFragmentManager();
        FragmentTransaction frgTrans = manager.beginTransaction();
        frgTrans.replace(android.R.id.content, detailsFragment);
        frgTrans.addToBackStack("pm_fragment");
        frgTrans.commit();
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
        getLoaderManager().restartLoader(0, null, this);
        return true;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {

        System.out.println("The value of Filter is : "+mCurFilter); 
        // Run query
        Uri baseUri;

        if (mCurFilter != null) {
            baseUri = Uri.withAppendedPath(ContactsContract.CommonDataKinds.Phone.CONTENT_FILTER_URI,
                    Uri.encode(mCurFilter));
        } else {
            baseUri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        }

        String[] projection = new String[] {
                ContactsContract.CommonDataKinds.Phone._ID,
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.NUMBER,
                }; 

        String selection = "((" + 
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " NOTNULL) AND (" +
                ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " != '' ))";
        String[] selectionArgs = null;
        String sortOrder = ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME + " COLLATE LOCALIZED ASC";

        return new CursorLoader(getActivity(), baseUri, projection, selection, selectionArgs, sortOrder);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor data) {
        mAdapter.swapCursor(data);
    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        // TODO Auto-generated method stub
        mAdapter.swapCursor(null);      
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        // TODO Auto-generated method stub
        return false;
    }

}

DetailsFragment.java displaying the details of clicked list item:

package com.android.myactiobartabs;

import android.app.ActionBar;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class DetailsFragment extends Fragment  {
    TextView textDetail1;
    TextView textDetail2;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);

        //Get ActionBar   and navigate UP
        ActionBar actionBar = getActivity().getActionBar();
        //      MenuButtonUtil.enableMenuButton(getActivity());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.details_fragment, container, false);

        textDetail1 = (TextView)view.findViewById(R.id.textDetail1);
        textDetail2 = (TextView)view.findViewById(R.id.textDetail2);

        Bundle bundle = getArguments();
        if(bundle != null){
            String name = bundle.getString("CONTACT_NAME");
            String number = bundle.getString("CONTACT_NUMBER");
            textDetail1.setText(""+number);
            textDetail2.setText(""+name);
        }

        //      getFragmentManager().popBackStack();

        return view;
    }


    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {

        inflater.inflate(R.menu.details_fragment_actionitems, menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

        /*case android.R.id.home:

            FragmentManager manager= getActivity().getFragmentManager();
            manager.popBackStack("pm_fragment", FragmentManager.POP_BACK_STACK_INCLUSIVE);
            FragmentTransaction frgTrans = manager.beginTransaction();
            frgTrans.commit();
            getActivity().getActionBar().setDisplayHomeAsUpEnabled(false);
            getActivity().getActionBar().setHomeButtonEnabled(false);

            return true;
         */
        case R.id.dt_action_search:
            Toast.makeText(getActivity(),"Text_SEARCH!",Toast.LENGTH_SHORT).show();
            return true;
        case R.id.dt_action_delete:
            Toast.makeText(getActivity(),"Text_DELETE!",Toast.LENGTH_SHORT).show();
            return true;
        case R.id.dt_action_edit:
            Toast.makeText(getActivity(),"Text_EDIT!",Toast.LENGTH_SHORT).show();
            return true;
        case R.id.dt_action_add_person:
            final Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
            startActivity(intent);
            return true; 
        default:
            return super.onOptionsItemSelected(item);
        }
    }    

}

TagFragmentTwo.java displaying the simple txt on clicking FragmentB tab.

package com.android.myactiobartabs;

import android.app.ActionBar;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;


public class TabFragmentTwo extends Fragment{


        TextView textDetail;

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);

            ActionBar actionBar = getActivity().getActionBar();

        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {


            View view = inflater.inflate(R.layout.tab_fragment, container, false);

            textDetail = (TextView)view.findViewById(R.id.simpleTxt);

            Bundle bundle = getArguments();
            if(bundle != null){
                String simpleTxt = bundle.getString("Fragment");
                textDetail.setText(""+simpleTxt);
            }

            return view;
        }


        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Auto-generated method stub
        super.onCreateOptionsMenu(menu, inflater);
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
        // TODO Auto-generated method stub
        return super.onOptionsItemSelected(item);
        }

    }

Solution

  • I would suggest you to clear the backstack of your fragment whenever you click on 2DFragment or 3D Fragment. At that click event first pop the backstack of fragment and then load the new fragment. It will work for sure.

    Write the below code on click of your tabs before loading the new fragment.

                FragmentManager fm = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
                fm.popBackStack();
    

    EDITED:

    Change code in your MainActivity as below:

    else    if(tab.getPosition() == 1){
    
        FragmentManager manager= getFragmentManager();
        FragmentTransaction frgTrans = manager.beginTransaction();
        manager.popBackStack();
    
          TabFragmentTwo tabFragmentTwo= new TabFragmentTwo();
        Bundle bundle = new Bundle();
        bundle.putString("Fragment", "2nd Fragment");
    
        tabFragmentTwo.setArguments(bundle);
        frgTrans.replace(android.R.id.content, tabFragmentTwo);
        frgTrans.commit();
    }
    
    else {
        FragmentManager manager= getFragmentManager();
        FragmentTransaction frgTrans = manager.beginTransaction();
        manager.popBackStack();
         TabFragmentThree tabFragmentThree= new TabFragmentThree();
        Bundle bundle = new Bundle();
        bundle.putString("Fragment", "3rd Fragment");
    
        tabFragmentThree.setArguments(bundle);
    
        frgTrans.replace(android.R.id.content, tabFragmentThree);
        frgTrans.commit();
        }