Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Android

MainActivity Extending a NavigationActivity. On button click nav not showing up

When I click the button in the actionBar that is supposed to make the nav apear, it doesnt.

baseActivity.java

package com.tsm.stormy.ui;

/**
 * Created by Tegh SM on 8/19/2016.
 */

import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.Toast;

import com.google.android.gms.maps.model.LatLng;
import com.google.gson.Gson;
import com.sdsmdg.tastytoast.TastyToast;
import com.tsm.stormy.R;

import java.util.ArrayList;
import java.util.TreeMap;

/**
 * @author dipenp
 *
 * This activity will add Navigation Drawer for our application and all the code related to navigation drawer.
 * We are going to extend all our other activites from this BaseActivity so that every activity will have Navigation Drawer in it.
 * This activity layout contain one frame layout in which we will add our child activity layout.
 */
public class BaseActivity extends AppCompatActivity {
    private static final String TAG = BaseActivity.class.getSimpleName();
    protected FrameLayout frameLayout;
    protected ListView mDrawerList;
    protected ArrayList listArray;
    protected static int position;
    private static boolean isLaunch = true;
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle actionBarDrawerToggle;
    SharedPreferences mSharedPreferences;
    TreeMap<String, LatLng> savedLocations;
    ArrayList<String> locationNames;



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


        frameLayout = (FrameLayout)findViewById(R.id.content_frame);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // set a custom shadow that overlays the main content when the drawer opens
        //mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        if (getAllLocations() == null) {
            listArray = new ArrayList();
            listArray.add("No Locations Added");
        } else {
            listArray = getLocationNames();
        }

        // set up the drawer's list view with items and click listener
        mDrawerList.setAdapter(new ArrayAdapter<>(this, R.layout.nav_list_item, listArray));
        mDrawerList.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                                    int position, long id) {

                //openActivity(position);
            }
        });

        // enable ActionBar app icon to behave as action to toggle nav drawer
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        // ActionBarDrawerToggle ties together the the proper interactions between the sliding drawer and the action bar app icon
        actionBarDrawerToggle = new ActionBarDrawerToggle(
                this,      /* host Activity */
                mDrawerLayout,
                /* DrawerLayout object */
               R.drawable.ic_arrow_to_drawer,     /* nav drawer image to replace 'Up' caret */
                R.string.open_drawer,       /* "open drawer" description for accessibility */
                R.string.close_drawer)      /* "close drawer" description for accessibility */
        {
            @Override
            public void onDrawerClosed(View drawerView) {
                getSupportActionBar().setTitle("Locations");
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
                super.onDrawerClosed(drawerView);
            }

            @Override
            public void onDrawerOpened(View drawerView) {
                getSupportActionBar().setTitle(getString(R.string.app_name));// creates call to onPrepareOptionsMenu()
               supportInvalidateOptionsMenu();
                super.onDrawerOpened(drawerView);
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
            }

            @Override
            public void onDrawerStateChanged(int newState) {
                super.onDrawerStateChanged(newState);
            }
        };
        mDrawerLayout.setDrawerListener(actionBarDrawerToggle);


        /**
         * As we are calling BaseActivity from manifest file and this base activity is intended just to add navigation drawer in our app.
         * We have to open some activity with layout on launch. So we are checking if this BaseActivity is called first time then we are opening our first activity.
         * */
        if(isLaunch){
            /**
             *Setting this flag false so that next time it will not open our first activity.
             *We have to use this flag because we are using this BaseActivity as parent activity to our other activity.
             *In this case this base activity will always be call when any child activity will launch.
             */
            isLaunch = false;
            //openActivity(0);
        }
    }

    /**
     * @param position
     *
     * Launching activity when any list item is clicked.
     */
    /*protected void openActivity(int position) {

        *//**
         * We can set title & itemChecked here but as this BaseActivity is parent for other activity,
         * So whenever any activity is going to launch this BaseActivity is also going to be called and
         * it will reset this value because of initialization in onCreate method.
         * So that we are setting this in child activity.
         *//*
//  mDrawerList.setItemChecked(position, true);
//  setTitle(listArray[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
        BaseActivity.position = position; //Setting currently selected position in this field so that it will be available in our child activities.

        switch (position) {
            case 0:
                startActivity(new Intent(this, Item1Activity.class));
                break;
            case 1:
                startActivity(new Intent(this, Item2Activity.class));
                break;
            case 2:
                startActivity(new Intent(this, Item3Activity.class));
                break;
            case 3:
                startActivity(new Intent(this, Item4Activity.class));
                break;
            case 4:
                startActivity(new Intent(this, Item5Activity.class));
                break;

            default:
                break;
        }

        Toast.makeText(this, "Selected Item Position::"+position, Toast.LENGTH_LONG).show();
    }*/

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.menu_main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        // The action bar home/up action should open or close the drawer.
        // ActionBarDrawerToggle will take care of this.
        if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    /*@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        getMenuInflater().inflate(R.menu.menu_main, menu);
        menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }*/

    @Override
    public void onBackPressed() {
        if(mDrawerLayout.isDrawerOpen(mDrawerList)){
            mDrawerLayout.closeDrawer(mDrawerList);
        }else {
            mDrawerLayout.openDrawer(mDrawerList);
        }
    }

    public void addLocation(LatLng latlng, String name) {

        mSharedPreferences = getPreferences(MODE_PRIVATE);
        SharedPreferences.Editor prefsEditor = mSharedPreferences.edit();
        Gson gson = new Gson();
        String json = gson.toJson(latlng);
        prefsEditor.putString(name, json);
        locationNames.add(name);
        prefsEditor.commit();

        String userData = mSharedPreferences.getString(name, json);

        if((userData.equals(json))){
            //password has not been saved...
            Log.d(TAG, "JSON LATLNG saved");
            TastyToast.makeText(BaseActivity.this, "Location Saved", 500, TastyToast.SUCCESS);
        }
        else{
            //password is already there...
            Log.d(TAG, "JSON LATLNG not saved");
            TastyToast.makeText(BaseActivity.this, "Location Unable to Save!", Toast.LENGTH_LONG, TastyToast.ERROR);

        }
    }

    private TreeMap<String, LatLng> getLocation(String name) {
        Gson gson = new Gson();
        String json = mSharedPreferences.getString(name, "");
        LatLng latlng = gson.fromJson(json, LatLng.class);
        TreeMap<String, LatLng> locations = new TreeMap<>();
        locations.put(name, latlng);
        return locations;
    }

    public TreeMap<String, LatLng> getAllLocations() {
        if (locationNames == null) {
            return savedLocations;
        } else {
            for (String name : locationNames) {
                LatLng latLng = getLocation(name).get(name);
                savedLocations.put(name, latLng);
            }
        }
        return savedLocations;
    }

    public ArrayList<String> getLocationNames() {
        for (int i = 0;  i < getAllLocations().size(); i++) {
            ArrayList<String> locationNames = new ArrayList<>();
            locationNames.add(getAllLocations().keySet().toString());
        }
        return locationNames;
    }
}

I tried this

@Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        getMenuInflater().inflate(R.menu.menu_main, menu);
        menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }

but Menu is null, even though I used in it onCreateOptionsMenu

NavDrawer.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

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

    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#111"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>

menu_main.xml

<?xml version="1.0" encoding="utf-8"?>

<menu
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="match_parent"
    android:layout_width="match_parent"
    app:theme="@style/ToolBarStyle">
    <item
    android:id="@+id/action_location"
    android:orderInCategory="300"
    android:title="My Location"
    android:icon="@drawable/ic_place_white_48dp"
    app:showAsAction="always" />

    <item
        android:id="@+id/action_nav"
        android:orderInCategory="300"
        android:title="My Location"
        android:icon="@drawable/icon"
        app:showAsAction="always" />

    <item
        android:id="@+id/action_add_location"
        android:orderInCategory="300"
        android:title="Add Location"
        android:icon="@drawable/ic_add_location_white_48dp"
        app:showAsAction="always" />

</menu>

Ben Jakuben Ben Deitch can you take a look at this

Edit: Since I extend the BaseActivity the drawer was supposed to open, but when I tested it as it's own activity in an intent, and open the nav it works.

Ben Jakuben
Ben Jakuben
Treehouse Teacher

Hi Tegh, apologies about my delayed reply here. Is this still an issue for you? I can't tell from your latest comment if you've achieved the result you're after yet. If not, email me your code zipped up or share a link to a repo and I can try to help troubleshoot it.

Ben Jakuben its fine. I'm not using this method of applying a nav drawer.