javaandroidxmlmaterial-designnavigation-drawer

Cannot Set Up Android Nav Drawer in Action Bar


I am trying to set up the Android Nav Drawer with an action bar. I am having difficulty setting the icon for the Nav Drawer and generating all of the list items as well. Below is my code, I am currently generating a NullPointer Exception:

Crash:

                                                                                  --------- beginning of crash
04-20 18:02:03.690 13170-13170/com.sourcey.materialloginexample E/AndroidRuntime: FATAL EXCEPTION: main
                                                                                  Process: com.sourcey.materialloginexample, PID: 13170
                                                                                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.sourcey.materialloginexample/com.troychuinard.fanpolls.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference
                                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
                                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
                                                                                      at android.app.ActivityThread.access$800(ActivityThread.java:151)
                                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
                                                                                      at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                                      at android.os.Looper.loop(Looper.java:135)
                                                                                      at android.app.ActivityThread.main(ActivityThread.java:5254)
                                                                                      at java.lang.reflect.Method.invoke(Native Method)
                                                                                      at java.lang.reflect.Method.invoke(Method.java:372)
                                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                                                                                   Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference
                                                                                      at com.troychuinard.fanpolls.MainActivity.onCreate(MainActivity.java:71)
                                                                                      at android.app.Activity.performCreate(Activity.java:5990)
                                                                                      at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
                                                                                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
                                                                                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387) 
                                                                                      at android.app.ActivityThread.access$800(ActivityThread.java:151) 
                                                                                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303) 
                                                                                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                                      at android.os.Looper.loop(Looper.java:135) 
                                                                                      at android.app.ActivityThread.main(ActivityThread.java:5254) 
                                                                                      at java.lang.reflect.Method.invoke(Native Method) 
                                                                                      at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
                                                                                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

  MainActivity:

    public class MainActivity extends AppCompatActivity implements HomePollsFragment.OnFragmentInteractionListener {

    private Toolbar toolbar;

    private Firebase mPollsRef;
    private ViewPager mPager;

    private ScreenSlidePagerAdapter mPagerAdapter;
    private DateFormat mDateFormat;
    private Date mDate;
    private String mCurrentDateString;
    private ValueEventListener v;
    private String[] mPlanetTitles;
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = (Toolbar) findViewById(R.id.action_tool_bar);
        setSupportActionBar(toolbar);
        Firebase.setAndroidContext(this);


        mPollsRef = FirebaseUtil.FIREBASE.child("Polls");

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                toolbar,  /* nav drawer icon to replace 'Up' caret */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */) {

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

        mDrawerList = (ListView) findViewById(R.id.left_drawer);
        ArrayList<String> drawerTitleArray = new ArrayList<>();
        drawerTitleArray.add(0, "TEST");
        drawerTitleArray.add(1, "TEST 1");
        // Set the adapter for the list view
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, drawerTitleArray));


        // TODO: Add Fragment Code to check if savedInstanceState == null; add at Activity Level?
        // Check that the activity is using the layout version with
        // the fragment_container FrameLayout


        //set up viewpager for current day
        mPager = (ViewPager) findViewById(R.id.home_polls_viewpager_fragment_container);
        mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
        mPager.setAdapter(mPagerAdapter);


        //get current date to apply to Viewpager
        mDateFormat = new SimpleDateFormat("MM-dd-yyyy");
        mDate = new Date();
        mCurrentDateString = mDateFormat.format(mDate);

        // TODO: Checkn if AuthStateListenerNecessary
        //Determine whether necessary to use an AuthStateListener here
//        mUserRef.addAuthStateListener(new Firebase.AuthStateListener() {
//            @Override
//            public void onAuthStateChanged(AuthData authData) {
//                if (authData == null) {
//                    Intent backToSignIn = new Intent(getApplication(), SignupActivity.class);
//                    startActivity(backToSignIn);
//                    finish();
//                }
//            }
//        })

    }


    @Override
    protected void onStart() {
        super.onStart();

        v = new ValueEventListener() {
            //testing methodology of adding children
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                int pollsAvailable = (int) dataSnapshot.child(mCurrentDateString).getChildrenCount();
                mPagerAdapter.setPollsAvailable(pollsAvailable);
                Log.i("TAG", "There are " + String.valueOf(pollsAvailable) + " children in today's poll count.");
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        };

        mPollsRef.addValueEventListener(v);

    }

    @Override
    protected void onStop() {
        super.onStop();
        mPollsRef.removeEventListener(v);

    }

    @Override
    public void onFragmentInteraction(Uri uri) {

    }


    class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
        private int pollsAvailable = 0;

        //fragment adapter constructor
        public ScreenSlidePagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            return HomePollsFragment.newInstance(position);
        }

        @Override
        public int getCount() {
            return pollsAvailable;
        }

        public void setPollsAvailable(int pollsAvailable) {
            this.pollsAvailable = pollsAvailable;
            this.notifyDataSetChanged();
        }
    }





    @Override
    public void onBackPressed() {
        super.onBackPressed();
        if (mPager.getCurrentItem() == 0) {
            // If the user is currently looking at the first step, allow the system to handle the
            // Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed();
        } else {
            // Otherwise, select the previous step.
            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
        }
    }
}

XML:

 <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"
    android:orientation="vertical">

    <LinearLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/action_tool_bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/actionRed">

        </android.support.v7.widget.Toolbar>

        <android.support.v4.view.ViewPager
            android:id="@+id/home_polls_viewpager_fragment_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </android.support.v4.view.ViewPager>

    </LinearLayout>

    <!-- The navigation drawer -->
    <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>

Solution

  • I do it like this:

     android.support.v7.app.ActionBar actionBar = getSupportActionBar();
            if(actionBar != null){
                actionBar.setDisplayHomeAsUpEnabled(true);
                actionBar.setHomeButtonEnabled(true);
            }
    

    This should solve the java.lang.NullPointerException.

    "and generating all of the list items as well"

    I cant see whats the problem here. Could you explain it a little bit?

    The icon - Three horizontal lines in closed mode, a back arrow in opened mode with a nice smooth animation:

      drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
            drawerToggle = new ActionBarDrawerToggle(
                    this,                  /* host Activity */
                    drawerLayout,         /* DrawerLayout object */
                    toolbar,  /* nav drawer icon to replace 'Up' caret */
                    R.string.nav,  /* "open drawer" description */
                    R.string.nav  /* "close drawer" description */
            ) {
    
                /** Called when a drawer has settled in a completely closed state. */
                public void onDrawerClosed(View view) {
                    super.onDrawerClosed(view);
                    if(extra == null){
                        toolbar.setTitle(title);
                    }else{
                        toolbar.setTitle(title + " - " + extra);
                    }
                    isOpen = false;
                }
    
                /** Called when a drawer has settled in a completely open state. */
                public void onDrawerOpened(View drawerView) {
                    super.onDrawerOpened(drawerView);
                    actionBar.setTitle(R.string.nav);
                    isNavReady = true;
                    isOpen = true;
                }
            };
            drawerLayout.addDrawerListener(drawerToggle);
    
    @Override
        public boolean onOptionsItemSelected(MenuItem item){
            return drawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
        }
    
    
        @Override
        protected void onPostCreate(Bundle savedInstanceState) {
            super.onPostCreate(savedInstanceState);
            // Sync the toggle state after onRestoreInstanceState has occurred.
            drawerToggle.syncState();
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            drawerToggle.onConfigurationChanged(newConfig);
        }