Sal Aldana
Sal Aldana

Reputation: 1235

Drill Down Navigation with Fragments from NavigationDrawer

So I've been able to implement the built in NavigationDrawer in my Android app without any issues, and all my main Fragments are setup and work when selected.

Where I'm stuck is that in some fragments I will need to add a drill down type of feature when an item is selected, for example one Fragment is a list of customers, so selecting a customer should then push to the next fragment while still providing a back option to the user (I believe this would be done through the home button).

The problem I'm having is that with the NavigationDrawer template the home button is now the button for opening/closing the list, so I can't seem to figure out how I'm supposed to change the home button to be a back button, and I'm not sure if I'm presenting my next fragment correctly either. Below is the code for moving to a customers detail fragment when selected (note right now I'm not passing any data from the client list fragment to the client data frogmen yet, I just want to get the navigation setup properly first):

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_clients, container, false);

        thisActivity = this.getActivity();

        clientListView = (ListView)rootView.findViewById(R.id.clientListView);



        return rootView;
    }

 //later after the list view adapter has been updated with data
 clientListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String name = dataList.get(position).clientName;
                Log.d("message", "the client clicked on is: " + name);
                Fragment fragment = new FragmentClientDetail();
                FragmentManager manager = thisActivity.getFragmentManager();
                FragmentTransaction transaction = manager.beginTransaction();
                transaction.replace(R.id.container, fragment);
                transaction.addToBackStack("clientdetail");
                transaction.commit();

            }
        });

So my questions mainly are, first am I actually handling the navigation correctly by replacing the container with the new fragment and then secondly what do I need to change in my second fragment to enable the back button as the home button instead of the NavigationDrawer?

EDIT 1

So after Raghunandan's comment lead me down some extra google searching I was able to get the ListView to pull up the next fragment correctly, and the callback method is being called but for some reason I still can't get the ActionBar Home button to switch from the NavigationDrawer style to a the normal navigation action bar with the back arrow. Right now it still defaults as the NavigationDrawer type of button that still pulls up the navigation menu. So basically what I want to accomplish is that when I'm the "main" fragments of the application then the Home Icon will perform the NavigationDrawer action and pull up the list of fragments to view, but then when drilling down sub-fragments the Home Icon should switch to just a back option button style of Icon. Here's what I've tried so far with the callback method in the fragment to push the sub fragments:

@Override
    public void callBackList(String fragmentName, String displayName) {
        Log.d("message", "callbacklist called");
        mTitle = fragmentName;
        displayTitle = displayName;
        //Push child fragment on top of current fragment
        Fragment fragment = new FragmentClientDetail();
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.container, fragment);
        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        transaction.addToBackStack(null);
        //Change action bar style to default action bar style with back button
        ActionBar actionBar = getActionBar();
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
        actionBar.setDisplayShowTitleEnabled(true);
        actionBar.setDisplayHomeAsUpEnabled(true);
        actionBar.setHomeButtonEnabled(true);
        actionBar.setTitle(title);
        transaction.commit();
        //call to update menu icons for child fragments that may be different than parent fragment
        invalidateOptionsMenu();
    }

Upvotes: 2

Views: 1032

Answers (2)

Sal Aldana
Sal Aldana

Reputation: 1235

Okay, so after a lot of reading and digging through the android docs I finally got it setup so that the subviews show the up caret and works as the back button, but when the main view is displayed then the navigation drawer is shown again. Here's what I ended up doing in case anyone else is trying to do the same (or if anyone finds a problem with how I did this and have a better solution).

//First in the NavigationDrawerFragment class that is created with the
//Drawer template I added two methods, that will adjust the drawer's view
//change action bar to show up caret
    public static void showSubActionBar() {
        mDrawerToggle.setDrawerIndicatorEnabled(false);
    }
    //change action bar to show navigation drawer icon
    public static void showNavActionBar() {
        mDrawerToggle.setDrawerIndicatorEnabled(true);
    }

//Then in my MainActivity class I add a small method that uses a counter
// to determine if a user is in a sub level (since some 
//fragments may have up to 4 sub levels) or back on the main view 
//and updates the ActionBar
public void subLevelCounter(int counter) {

       levelCounter = levelCounter + counter;
        if (levelCounter > 0) {
            NavigationDrawerFragment.showSubActionBar();
        }
        else {
            NavigationDrawerFragment.showNavActionBar();

        }
        invalidateOptionsMenu();

    }

//So now when the back button is visible and pressed I updated the counter
//and call the onBackPressed method
if (item.getItemId() == android.R.id.home) {
            ((MainActivity) getActivity()).subLevelCounter(-1);
            getActivity().onBackPressed();
            return true;
        }

//And when I'm drilling down I just add this line before calling the 
//backlist method to perform the navigation
                ((MainActivity) thisActivity).subLevelCounter(1);

Upvotes: 1

Raghunandan
Raghunandan

Reputation: 133560

Yes you need to add/replace fragments to the container based on list item click

You can use interface as a callback to the activity.

Fragment1-->HostingActivity-->Fragment2. Add make sure you add fragments to backstack.

http://developer.android.com/training/basics/fragments/communicating.html

You can use

 getActivity().getActionBar().setHomeButtonEnabled(true);
 getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);

More info @

http://developer.android.com/training/implementing-navigation/ancestral.html

Example :

public interface ListItemCallback
{
      public void callBackList()
}

Then in fragment

ListItemCallback mCallback;
@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // This makes sure that the container activity has implemented
    // the callback interface. If not, it throws an exception
    try {
        mCallback = (ListItemCallback) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString()
                + " must implement ListItemCallback");
    }
}

Then

 clientListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String name = dataList.get(position).clientName;
            Log.d("message", "the client clicked on is: " + name);
            mCallback.callBackList();

        }
    });

Then in Activity

 public class MainActivity extends  Activity implements ListItemCallback
 {
  ...// rest of the code
  @Override
  public void callBackList(String name)
  {
        Fragment fragment = new FragmentClientDetail();
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.replace(R.id.container, fragment);
        transaction.addToBackStack("clientdetail");
        transaction.commit(); 
  } 

 }

Upvotes: 1

Related Questions