Question

In my Android app I have a slide out navigation drawer. When An item is selected in the navigation drawer, it loads the new fragment and highlights the item you clicked on in the navigation drawer.

My issue is that in the new fragment that loaded you can click on a new item within that fragment which loads a new fragment and still keeps the navigation drawer.

At this instance you are no longer on a fragment that is listed in the navigation drawer but the last item is still highlighted and then can not be clicked again to go back.

Any ideas on how I can un-highlight an item in the navigation drawer when it is not one of my main fragments and then be re-highlighted if on one of the main fragments?

Here is my navigation drawer code:

public class MainDrawer2 extends FragmentActivity
{
    private static final String EXTRA_NAV_ITEM    = "extraNavItem";
    private static final String STATE_CURRENT_NAV = "stateCurrentNav";

    private ActionBarDrawerToggle mDrawerToggle;
    private DrawerLayout mDrawerLayout;

    private NavDrawerListAdapter mDrawerAdapter;
    private ListView mDrawerList;

    private CharSequence mTitle;
    private CharSequence mDrawerTitle;

    private MainNavItem mCurrentNavItem;




    public static Intent createLaunchFragmentIntent(Context context, MainNavItem navItem)
    {
        return new Intent(context, MainDrawer2.class)
                .putExtra(EXTRA_NAV_ITEM, navItem.ordinal());
    }



    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_main);

        Crashlytics.start(this);



        mTitle = mDrawerTitle = getTitle();
        mDrawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
        mDrawerList   = (ListView)findViewById(R.id.drawer);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        enableHomeButtonIfRequired();

        mDrawerAdapter = new NavDrawerListAdapter(getApplicationContext());
        mDrawerList.setAdapter(mDrawerAdapter);
        mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id)
            {
                displayNavFragment((MainNavItem)parent.getItemAtPosition(position));
            }
        });

        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                R.drawable.ic_drawer, R.string.app_name, R.string.app_name)
        {
            public void onDrawerClosed(View view)
            {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView)
            {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu();
            }
        };

        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if(getIntent().hasExtra(EXTRA_NAV_ITEM)){
            MainNavItem navItem = MainNavItem.values()
                    [getIntent().getIntExtra(EXTRA_NAV_ITEM,
                    MainNavItem.STATISTICS.ordinal())];
            displayNavFragment(navItem);
        }
        else if(savedInstanceState != null){
            mCurrentNavItem = MainNavItem.values()
                    [savedInstanceState.getInt(STATE_CURRENT_NAV)];
            setCurrentNavItem(mCurrentNavItem);
        }
        else{
            displayNavFragment(MainNavItem.STATISTICS);
        }
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    private void enableHomeButtonIfRequired()
    {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH){
            getActionBar().setHomeButtonEnabled(true);
        }
    }
    public void setActionBarTitle(String title) {
        getActionBar().setTitle(title);
    }


    @Override
    public void setTitle(CharSequence title)
    {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState)
    {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig)
    {
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggles
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

    @Override
    protected void onSaveInstanceState(Bundle outState)
    {
        super.onSaveInstanceState(outState);
        outState.putInt(STATE_CURRENT_NAV, mCurrentNavItem.ordinal());
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu)
    {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    /*
    @Override
    public boolean onPrepareOptionsMenu(Menu menu)
    {
        // if nav drawer is opened, hide the action items
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
    */



    private void displayNavFragment(MainNavItem navItem)
    {
        if(navItem == mCurrentNavItem){
            return;
        }
        Fragment fragment = Fragment.instantiate(this,
                navItem.getFragClass().getName());
        if(fragment != null){

            getSupportFragmentManager().beginTransaction()
                    .replace(R.id.main, fragment)
                    .commit();
            setCurrentNavItem(navItem);
        }
    }

    private void setCurrentNavItem(MainNavItem navItem)
    {
        int position = navItem.ordinal();
        // If navItem is in DrawerAdapter
        if(position >= 0 && position < mDrawerAdapter.getCount()){
            mDrawerList.setItemChecked(position, true);
        }
        else{
            // navItem not in DrawerAdapter, de-select current item
            if(mCurrentNavItem != null){
                mDrawerList.setItemChecked(mCurrentNavItem.ordinal(), false);
            }
        }
        mDrawerLayout.closeDrawer(mDrawerList);
        setTitle(navItem.getTitleResId());
        mCurrentNavItem = navItem;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                if(mDrawerLayout.isDrawerOpen(mDrawerList)) {
                    mDrawerLayout.closeDrawer(mDrawerList);
                }
                else {
                    mDrawerLayout.openDrawer(mDrawerList);
                }
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }




    public void goToSearch(MenuItem item){

        //go to search page
        Fragment Fragment_one;
        FragmentManager man= getSupportFragmentManager();
        FragmentTransaction tran = man.beginTransaction();
        Fragment_one = new Search();

        tran.replace(R.id.main, Fragment_one);//tran.
        tran.addToBackStack(null);
        tran.commit();

    }

    public void scanBarcode(MenuItem item){

        //open scanner
        IntentIntegrator scanIntegrator = new IntentIntegrator(this);
        scanIntegrator.initiateScan();



    }

    public void onActivityResult(int requestCode, int resultCode, Intent intent) {

        //retrieve scan result
        IntentResult scanningResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
        if (scanningResult != null) {
            //we have a result

            String scanContent = scanningResult.getContents();

            //todo: set scan content into setting, load new fragment which calls async task below. New
            //todo: fragment will have same ui as search. :-)
            Fragment Fragment_one;
            FragmentManager man= this.getSupportFragmentManager();
            FragmentTransaction tran = man.beginTransaction();
            Fragment_one = new BarcodeFrag(scanContent);
            tran.replace(R.id.main, Fragment_one);//tran.
            tran.addToBackStack(null);
            //tran.commit();
            tran.commitAllowingStateLoss();


        }

        else{
            Toast toast = Toast.makeText(getApplicationContext(),
                    "No scan data received!", Toast.LENGTH_SHORT);
            toast.show();
        }

    }


}

then I have an enum called main nav item:

public enum MainNavItem
{
    // Displayed in NavDrawerListAdapter
    STATISTICS("Your Statistics",   R.layout.statistics_pagelayout,     StatisticsTab.class),
    DISCOVER  ("Discover",          R.layout.activity_discover,         DiscoverTab.class),
    PORTFOLIO ("Portfolio",         R.layout.activity_portfolio,        Portfolio.class),
    LISTS      ("Your Lists",       R.layout.activity_search,           AllLists.class),
    NEWS      ("News",              R.layout.activity_news,             NewsWeb.class),
    Find      ("Nearby Breweries",  R.layout.beer_location_list,        FindBrewery.class),
    CONTACT   ("Contact",           R.layout.activity_contact,          ContactPage.class),
    // Items NOT displayed in NavDrawerListAdapter
    SEARCH    ("Search",            R.layout.activity_search,           Search.class),
    ;

    private static MainNavItem LAST_NAV_ITEM = CONTACT;

    private String mTitleResId;
    private int mLayoutResId;
    private Class<? extends Fragment> mFragClass;


    private MainNavItem(String titleResId, int layoutResId, Class<? extends Fragment> fragClass)
    {
        mTitleResId  =  titleResId;
        mLayoutResId = layoutResId;
        mFragClass   = fragClass;
    }

    public int getLayoutResId()
    {
        return mLayoutResId;
    }

    public String getTitleResId()
    {
        return mTitleResId;
    }

    public Class<? extends Fragment> getFragClass()
    {
        return mFragClass;
    }

    public static MainNavItem[] getNavAdapterItems()
    {
        int count = LAST_NAV_ITEM.ordinal() + 1;

        MainNavItem[] adapterItems = new MainNavItem[count];
        for(int i = 0; i < count; i++){
            adapterItems[i] = values()[i];
        }

        return adapterItems;
    }
}

UPDATE:

I just tried to comment out these two lines to turn off highlighting in general so a user can re-select an item again in my navigation drawer.

private void setCurrentNavItem(MainNavItem navItem)
    {
        int position = navItem.ordinal();
        // If navItem is in DrawerAdapter
        if(position >= 0 && position < mDrawerAdapter.getCount()){
            //mDrawerList.setItemChecked(position, true);
        }
        else{
            // navItem not in DrawerAdapter, de-select current item
            if(mCurrentNavItem != null){
                //mDrawerList.setItemChecked(mCurrentNavItem.ordinal(), false);
            }
        }
        mDrawerLayout.closeDrawer(mDrawerList);
        setTitle(navItem.getTitleResId());
        mCurrentNavItem = navItem;
    }

When the app boots for the firs time now, nothing is highlighted, but when I click on something it get highlighted and I can not click it again to reload that fragment. Any other ideas?

Was it helpful?

Solution 2

Figured it out. The simplest way to not have an item in your draw be highlighted is in your xml for the draw linst, choiceMode should be none:

<FrameLayout
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
</FrameLayout>

<ListView
    android:id="@+id/drawer"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:divider="@android:color/white"
    android:background="@android:color/black"
    android:choiceMode="none"/>

OTHER TIPS

I just grouped my items as given below, android:checkableBehavior="none" this line is very important and make sure it should be none.

<group android:checkableBehavior="none">
    <item
        android:id="@+id/nav_home"
        android:icon="@drawable/left_menu_home"
        android:title="@string/home" />
    <item
        android:id="@+id/nav_account_settings"
        android:icon="@drawable/left_menu_account_settings"
        android:title="@string/accountSettings" />

</group>

You can unselect a navigation drawer menu item by calling menuItem.setChecked(false);

Any ideas on how I can un-highlight an item in the navigation drawer when it is not one of my main fragments

    int toClear=mDrawerList.getCheckedItemPosition();

    if (toClear >= 0) {
      mDrawerList.setItemChecked(toClear, false);
    }

and then be re-highlighted if on one of the main fragments?

Call setItemChecked() with the position that corresponds to the visible fragment and true for the second parameter.

This sample project demonstrates this. My use of post() to control when we go about updating the checked states in the ListView is a bit sloppy, but it'll suffice.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top