Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slide out navigation items staying highlighted

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?

like image 322
Mike Avatar asked Apr 20 '14 21:04

Mike


1 Answers

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>

like image 54
Waheed Nazir Avatar answered Sep 21 '22 21:09

Waheed Nazir