0

I'm new to Android / Kotlin and I have an application with multiple activities. So far I have created all the activities needed and the app works fine except for the fact now I need to add a Navigation Drawer.

Coming from iOS, I designed all my layouts thinking I can add the Navigation Drawer after:

<?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"
    android:background="@color/backgroundColor"
    android:backgroundTint="@color/backgroundColor">

    <RelativeLayout
        android:id="@+id/mainRelativeLayout"
        android:layout_width="match_parent"
        android:layout_height="44dp"
        android:background="@drawable/navbar_border"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <ImageView
            android:id="@+id/ivNavBarLogo"
            android:layout_width="102dp"
            android:layout_height="24dp"
            android:layout_centerHorizontal="true"
            android:layout_centerVertical="true"
            android:contentDescription="@string/empty_description"
            app:srcCompat="@mipmap/navbar_logo"/>

        <ImageButton
            android:id="@+id/btnSideMenu"
            android:layout_width="25dp"
            android:layout_height="15dp"
            android:layout_centerVertical="true"
            android:layout_marginStart="15dp"
            android:background="@mipmap/sidemenu_button"
            android:contentDescription="@string/empty_description"
            app:srcCompat="@mipmap/sidemenu_button"/>
    </RelativeLayout>

    <!-- STUFF TO BE ADDED THERE -->

</android.support.constraint.ConstraintLayout>

My intention was to create a NavigationDrawer activity and call it when tapping the btnSideMenu on each activity.

However, I've been trying to get around this for a few days now without any luck. I never thought such a basic feature could be so hard to implement. I tried almost every suggestion and example found here, and also this: https://developer.android.com/training/implementing-navigation/nav-drawer.html

Am I thinking this issue the wrong way? Is there any way of doing this without having to recreate all my activities based on the template provided by Android Studio or using fragments?

LE: Forgot to mention that I removed the ActionBar from all activities.

daydr3am3r
  • 920
  • 4
  • 12
  • 31
  • 1
    The navigation drawer is part of your activity(view controller). So, you need to treat is as another view in you activity. So, it needs to be in your xml too. The link you provide does say that in the xml the nav drawer needs to be specified and you need to implement some Kotlin code for it in your activity. If it's all to confusing for you, create a new activity from Android Studio and select the nav drawer activity, it has all the boiler plate done for you, the move all your logic to it. – rgv Mar 26 '18 at 20:26
  • @rgv - I created empty activities. I have no navigation drawer. Or this is not what you meant? – daydr3am3r Mar 26 '18 at 20:28
  • 1
    @rgv - Moving the logic from the template provided by AS was my first intention and I am seeing NullPointerException and an app crush on run. I'll give this another try, so far it seems the best idea for me. – daydr3am3r Mar 26 '18 at 20:33
  • 1
    Right click on your app module, then select new, then select activity from it, then select Navigation Drawer activity – rgv Mar 26 '18 at 20:34
  • Check out this [question](https://stackoverflow.com/questions/19451715/same-navigation-drawer-in-different-activities) – Rene Ferrari Mar 26 '18 at 20:35
  • Well you have to either duplicate the navigation drawer in each Activity, or you have to use fragments. – EpicPandaForce Mar 27 '18 at 20:08

2 Answers2

1

To add a navigation drawer to multiple activities without going through and re-writing every activity's layout, you can leverage a base activity class and a ViewStub tag.

Create a layout like this (I'll refer to it as navdrawer_activity.xml later):

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:openDrawer="start">

    <ViewStub
        android:id="@+id/navdrawer_stub"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <!-- 
         your drawer here
         you can use android.support.design.widget.NavigationView
         or some other view if you want 
    -->

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

Then create a class for all of your activities to extend:

public class NavDrawerActivity extends AppCompatActivity {

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

    @Override
    public final void setContentView(@LayoutRes int layoutResID) {
        ViewStub stub = findViewById(R.id.navdrawer_stub);
        stub.setLayoutResource(layoutResID);
        stub.inflate();
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // set up nav drawer as normal, using whatever
        // callback methods or helper methods you want
    }
}

With these in place, the only thing you have to do is change any activity where you want the nav drawer to extend NavDrawerActivity instead of AppCompatActivity.

Ben P.
  • 52,661
  • 6
  • 95
  • 123
0

Well as the guide you included says:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout ...>

    <!-- Layout to contain contents of main body of screen (drawer will slide over this) -->
    <content goes here
        ... />

    <!-- Container for contents of drawer -->
    <left pane of drawer goes here
        ...
        android:layout_gravity="start" />

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

You could define the left pane of the drawer as a compound view, and the content as a compound view. Kinda like this:

your_view.xml

<YourView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button android:id="@+id/..."
        android:layout_width="..."
        android:layout_height="..."
        android:layout_centerInParent="true"/>
</YourView>

And

public class YourView extends RelativeLayout {
    public YourView(Context context) {
        super(context);
    }

    public YourView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    // ... two more constructors are possible here

    private Button button;

    @Override
    public void onFinishInflate() {
        super.onFinishInflate();
        button = findViewById(R.id.button);
        button.setOnClickListener((view) -> {
            ...
        }
    }
}

And you can do the same thing for the view of the left pane. Make sure you include the android:layout_gravity="start" as an attribute of <YourLeftPane in its xml.


And now you can do in your activity_whatever.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout ...>

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

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

</android.support.v4.widget.DrawerLayout>
EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428