extending navigation drawer activity to other activities
Asked Answered
O

6

10

I'm trying to create a navigation drawer activity so I can extend that activity and use the menu in all activities by following the answer given in this question Link but my test app keeps crashing, here's my code:

BaseActivity.java

public class BaseActivity extends Activity {

    public DrawerLayout drawerLayout;
    public ListView drawerList;
    public String[] layers;
    private ActionBarDrawerToggle drawerToggle;

    protected void onCreate(Bundle savedInstanceState) {
        // R.id.drawer_layout should be in every activity with exactly the same
        // id.
        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

        drawerToggle = new ActionBarDrawerToggle((Activity) this, drawerLayout,
                R.drawable.ic_drawer, 0, 0) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(R.string.hello_world);
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(R.string.hello_world);
            }
        };
        drawerLayout.setDrawerListener(drawerToggle);

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

        layers = getResources().getStringArray(R.array.planets_array);
        drawerList = (ListView) findViewById(R.id.left_drawer);
        drawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, android.R.id.text1, layers));

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        if (drawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);

    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        drawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        drawerToggle.onConfigurationChanged(newConfig);
    }
}

MainActivity.java

public class MainActivity extends BaseActivity {

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

}

activity_profile.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".ProfileActivity" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

</RelativeLayout>

Logcat

03-03 01:22:18.031: D/AndroidRuntime(27902): Shutting down VM
03-03 01:22:18.031: W/dalvikvm(27902): threadid=1: thread exiting with uncaught exception (group=0x2b542210)
03-03 01:22:18.041: E/AndroidRuntime(27902): FATAL EXCEPTION: main
03-03 01:22:18.041: E/AndroidRuntime(27902): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.slider/com.example.slider.MainActivity}: java.lang.NullPointerException
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1967)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1992)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.ActivityThread.access$600(ActivityThread.java:127)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1158)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.os.Handler.dispatchMessage(Handler.java:99)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.os.Looper.loop(Looper.java:137)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.ActivityThread.main(ActivityThread.java:4441)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at java.lang.reflect.Method.invokeNative(Native Method)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at java.lang.reflect.Method.invoke(Method.java:511)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at dalvik.system.NativeStart.main(Native Method)
03-03 01:22:18.041: E/AndroidRuntime(27902): Caused by: java.lang.NullPointerException
03-03 01:22:18.041: E/AndroidRuntime(27902):    at com.example.slider.BaseActivity.onCreate(BaseActivity.java:35)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at com.example.slider.MainActivity.onCreate(MainActivity.java:12)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.Activity.performCreate(Activity.java:4465)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
03-03 01:22:18.041: E/AndroidRuntime(27902):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1931)
03-03 01:22:18.041: E/AndroidRuntime(27902):    ... 11 more
Onshore answered 3/3, 2014 at 1:40 Comment(10)
Can you put the crash log (logcat) ?Sacrarium
@Sacrarium I've added the logcatOnshore
can you also post your activity_profile layout? I hope you have added drawer_layout in your activity_profile?Sacrarium
I've posted the activity_profile, I'm not sure what you mean by adding drawer_layout in the activity_profile, where does that have to be added?Onshore
Read this comment in BaseActivity : "// R.id.drawer_layout should be in every activity with exactly the same id." You need to have drawer_layout in your activity. Since you haven't declared it, it is crashing here by giving null pointer exceptionSacrarium
I'm still not too sure what you mean, I've seen the comment but not sure where it should go? I put "drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);" in the onCreate method on the MainActivity.java but I'm still not getting anythingOnshore
Drawer layout is a widget given by android. Follow the link below to understand it and declaring it in the layout file. Till you dont declare it in layout, how can you use it in code? check this link : developer.android.com/training/implementing-navigation/…Sacrarium
I hope you understand now, how you need to alter the code of your activity_profile.xml to include drawer_layout widget and this will make you concept also more clear about drawer layout..Sacrarium
I think I understand now, I'll try and add the DrawerLayout to the activity_profile.xml and I'll let you know if it works, thanks for your help!Onshore
Happy to help :) .. Do let me know in case it works. Will convert my comment into answer and if you like, you may accept it..Sacrarium
C
5

In the main activity you have to call super.onCreate(savedInstanceState) after setContentView()

Converter answered 1/7, 2014 at 18:16 Comment(0)
P
5

The problem appears that the base class is not aware of the layout. Not sure how or why it worked for others without having to do something like this.. but I am new to Android.

I was getting the same error and solved by passing my layout to the base via onCreate.

So in the base, I modified onCreate to be like this:

protected void onCreate(Bundle savedInstanceState, int resLayoutID)
{
    super.onCreate(savedInstanceState);
    setContentView(resLayoutID);

Then, from my new activity, I have this:

@Override
protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState, R.layout.my_activity);

This code in my base now works instead of staying null:

drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
drawerList = (ListView) findViewById(R.id.left_drawer);

btw, this result was suggested to me by a friend and it worked for me.

Pseudohermaphrodite answered 5/4, 2014 at 18:6 Comment(0)
C
5

In the main activity you have to call super.onCreate(savedInstanceState) after setContentView()

Converter answered 1/7, 2014 at 18:16 Comment(0)
P
3

On the parent classBaseActivity:

  • declare a protected abstract int getLayoutId();

  • onCreate() I added the line

    setContentView(getLayoutId());
    

Now implement it on your subclass MainActivity something like:

 protected int getLayoutId() {
    return R.layout.activity_profile;
}

Please tell me if you know a better solution.

Pacificia answered 2/4, 2014 at 12:56 Comment(0)
A
2

As suggested by oli, you need to call setContentView(R.layout.activity_view) in your main activity.

BaseActivity's onCreate must be called once content view in Main Activity has been set as shown below :

public class BaseActivity extends Activity {
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // REST Navigation drawer initialization
    }

}



public class MainActivity extends BaseActivity {

    protected void onCreate(Bundle savedInstanceState) {

        setContentView(R.layout.activity_view);
        super.onCreate(savedInstanceState);

        // REST APPLICATION CODE
    }
}
Antiseptic answered 18/11, 2014 at 7:36 Comment(0)
I
1

Your xml file should look something like this, taken from the android website: http://developer.android.com/training/implementing-navigation/nav-drawer.html

<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">

    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
        <!-- Add content here -->
    </FrameLayout>

    <!-- The navigation drawer -->
    <ListView android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:choiceMode="singleChoice"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
Inexorable answered 3/3, 2014 at 10:32 Comment(10)
I have exactly the same error but the code above is already in my activity_base.xml so the app will keep on crashing..Ophthalmology
Yeah but is it in your other activities? You make an activity which extends baseactivity. In the xml file of that activity you should have something like I said above. So every activity should have this layout and the only thing you change is what is inside the framelayout (you put the view of your activity there)Inexorable
HomeActivity extends BaseActivity and both activities have above layoutOphthalmology
@Ophthalmology You keep mentioning that both activities have the same layout. BaseActivity should not have a layout. This is just a class which handles the drawer (so setContentView should not be in there). Also which activity do you start? you should start HomeActivity and not BaseActivityInexorable
yeah that's what I have.. I don't have a layout/activity_base.xml layout file, BaseActivity.java doesn't contain setContentView but still I have a NullPointerException at line 40 of BaseActivity which contains this: drawerLayout.setDrawerListener(drawerToggle); and at line 9 of HomeActivity (launcher activity): super.onCreate(savedInstanceState);Ophthalmology
@Ophthalmology Hmm thats very strange. Maybe you can post a new question and link me to it? Then I can see your whole code and help you solve this. Something probably went wrong while initializing the drawerToggle or the drawerLayoutInexorable
Hi Kevin, I followed your tutorial. It only works when I setContentView in the abstract view. Otherwise I get a NullPointerException. How can I solve this?Pacificia
@Pacificia thats strange, that shouldn't happen. Can you provide some logcat output or something? Perhaps in a new question for readabilityInexorable
@KevinvanMierlo i too faced same issue as Dediqated like yeah that's what I have.. I don't have a layout/activity_base.xml layout file, BaseActivity.java doesn't contain setContentView but still I have a NullPointerException at line 40 of BaseActivity which contains this: drawerLayout.setDrawerListener(drawerToggle); and at line 9 of HomeActivity (launcher activity): super.onCreate(savedInstanceState);Stacistacia
@Wiz25 Okay, few questions: you instantiated drawerToggle? Is there a drawerlayout in the layout file of HomeActivity? If you do can you post your code on gist (gist.github.com)? That way I can check what's wrong.Inexorable
K
1

In you MainActivity just put set setContentView(R.layout.activity_main) before

super.onCreate(savedInstanceState);

like below:

@Override
protected void onCreate(Bundle savedInstanceState) {
    setContentView(R.layout.activity_profile);
    super.onCreate(savedInstanceState);
}
Koressa answered 24/4, 2017 at 5:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.