-1

I have an app in which I added the Navigation Drawer by looking at the example android studio gives you. But now I want to add the drawer to other activities. To try to do this, I made an new project with the Navigation Drawer Activity that Android Studio gives you. I found that the easiest way to achieve this is to make a BaseActivity and extends all my other activities that need a Navigation Drawer from the BaseActivity Here is some of my code.

BaseActivity.java

package com.example.eddie.drawerapp2;
//I did not include the imports to make this shorter

public class BaseActivity extends AppCompatActivity implements
    NavigationView.OnNavigationItemSelectedListener
{
protected FrameLayout frameLayout;
private DrawerLayout drawer;
private NavigationView navView;

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


    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    android.support.v7.app.ActionBarDrawerToggle toggle = new android.support.v7.app.ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.addDrawerListener(toggle);
    toggle.syncState();

    frameLayout = (FrameLayout)findViewById(R.id.content_frame);
    drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
    navView = (NavigationView)findViewById(R.id.nav_view);

    navView.setNavigationItemSelectedListener(this);


}

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_camera) {
        // Handle the camera action
    } else if (id == R.id.nav_gallery) {

    } else if (id == R.id.nav_slideshow) {

    } else if (id == R.id.nav_manage) {

    } else if (id == R.id.nav_share) {

    } else if (id == R.id.nav_send) {

    }

    drawer.closeDrawer(GravityCompat.START);
    return true;
}
}

activity_base.xml

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

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

<android.support.design.widget.NavigationView
     android:id="@+id/nav_view"
     android:layout_width="wrap_content"
     android:layout_height="match_parent"
     android:layout_gravity="start"
     android:fitsSystemWindows="true"
    app:headerLayout="@layout/nav_header_main"
    app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

When I go to activity_base.xml and change it to design view it looks fine.

MainActivity.java

package com.example.eddie.drawerapp2;

//skip imports

public class MainActivity extends BaseActivity{

    private DrawerLayout drawer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        LayoutInflater inflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //inflate your activity layout here!
        drawer = (findViewById(R.id.drawer_layout));
        View contentView = inflater.inflate(R.layout.activity_main, null, false);
        drawer.addView(contentView, 0);

    }
}

activity_main.xml

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

        <include
            layout="@layout/app_bar_main"
            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" />

    </android.support.v4.widget.DrawerLayout>

app_bar_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.eddie.drawerapp2.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main" />

</android.support.design.widget.CoordinatorLayout>

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.eddie.drawerapp2.MainActivity"
    tools:showIn="@layout/app_bar_main">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

activity_main.xml and MainActivity.java have logic error. It just displays the content, and a blank tool bar. Swiping to open the NavigationDrawer doesn't do anything either. I really do not know what to do, this was just my attempt. Please help me, I am really stuck. What do I need to do to add the NavigationDrawer to the MainActivity and than other activities?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Eddie
  • 68
  • 8

1 Answers1

1

I have done this before, I think what you lack in your code for BaseActivity.java is overiding the setContentView methods so that content view can be set into the framelayout creating the behaviour of other activity implement this like subclasses.

1. BaseActivity.java

package com.example.eddie.drawerapp2;
//I did not include the imports to make this shorter

public class BaseActivity extends AppCompatActivity implements
    NavigationView.OnNavigationItemSelectedListener
{
protected FrameLayout frameLayout;
private DrawerLayout drawer;
private NavigationView navView;

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


    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    android.support.v7.app.ActionBarDrawerToggle toggle = new android.support.v7.app.ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.addDrawerListener(toggle);
    toggle.syncState();

    frameLayout = (FrameLayout)findViewById(R.id.content_frame);
    drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
    navView = (NavigationView)findViewById(R.id.nav_view);

    navView.setNavigationItemSelectedListener(this);


}

     /* Overriding all setContentView methods to put the content view to the FrameLayout frameLayout
  * so that, we can make other activity implementations looks like normal activity subclasses.
  */

@Override
public void setContentView(int layoutResID) {
    if (frameLayout != null) {
        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        View stubView = inflater.inflate(layoutResID, frameLayout, false);
        frameLayout.addView(stubView, lp);
    }
}

@Override
public void setContentView(View view) {
    if (frameLayout != null) {
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        frameLayout.addView(view, lp);
    }
}

@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
    if (frameLayout != null) {
        frameLayout.addView(view, params);
    }
}



@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
// Handle navigation view item clicks here.
    int id = item.getItemId();

    if (id == R.id.nav_camera) {
        // Handle the camera action
    } else if (id == R.id.nav_gallery) {

    } else if (id == R.id.nav_slideshow) {

    } else if (id == R.id.nav_manage) {

    } else if (id == R.id.nav_share) {

    } else if (id == R.id.nav_send) {

    }

    drawer.closeDrawer(GravityCompat.START);
    return true;
}
}
  1. Your MainActivity.java should something look like this MainActivity.java

    package com.example.eddie.drawerapp2;
    
    //skip imports
    
    public class MainActivity extends BaseActivity{
    
        private DrawerLayout drawer;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
        }
     }
    

3. activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true"
        tools:openDrawer="start">

        <include
            layout="@layout/app_bar_main"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />


    </RelativeLayout>
  • Thanks for the answer! I really appreciate it. One thing, in the ends of each `setContentView` method `super.setContentView` needs to be called. This gets the app to run, but it does not make the drawer work. Everything with `toolbar` had to be moved from `baseActivity` to `MainActivity.onCreate()`. as well as the `NavigationView` also had to be copied from `activity_base` to `activity_main` – Eddie Feb 28 '18 at 02:41
  • well thats interesting because that never happened in my case, especially with the navigationView. And in my case I completely removed the Toolbar. but I think you may hace to do some overrides for those as well in the BaseActivity.java – Rexford Nyarko Feb 28 '18 at 07:28
  • I did everythin like in the example you provided, and it cashes saying Attempt to invoke virtual method 'void android.support.v4.widget.DrawerLayout.addDrawerListener(android.support.v4.widget.DrawerLayout$DrawerListener)' on a null object reference and points to this `drawer.addDrawerListener(toggle);` in `BaseActivity` Can you please help – Eddie Mar 05 '18 at 22:28
  • ok will upload the codes of that project to github and share the link. I dont mind since it was strictly for educational purposes – Rexford Nyarko Mar 06 '18 at 19:22