Reputation: 5241
I have an activity with a navigation drawer that flicks between fragments. Nothing special.
However what I want is the action bar to appear at the top of the activity. The issue is that I keep getting a nullpointerexception
for the Actionbar
.
I've tried answers from the following pages:
getActionBar() returns Null (AppCompat-v7 21)
None of these have worked so I thought I'd submit my own question with my own code.
package com.jampez.smalltalk;
import com.jampez.smalltalk.fragments.HomeFragment;
import com.jampez.smalltalk.fragments.MessageFragment;
import com.jampez.smalltalk.fragments.PreferencesFragment;
import com.jampez.smalltalk.fragments.SettingsFragment;
import com.jampez.smalltalk.helper.SessionManager;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends FragmentActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
private String[] items;
int selectedPosition;
private SessionManager session;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().setTitle("");
// Session manager
session = new SessionManager(getApplicationContext());
if (!session.isLoggedIn()) {
// User is already logged in. Take him to main activity
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
finish();
}
items = getResources().getStringArray(R.array.menus);
// Getting reference to the DrawerLayout
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.drawer_list);
/* Creating an ArrayAdapter to add items to mDrawerList */
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.drawer_list_item, items);
mDrawerList.setAdapter(adapter);
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open) {
/* Called when drawer is closed */
public void onDrawerClosed(View view) {
//Put your code here
}
/* Called when a drawer is opened */
public void onDrawerOpened(View drawerView) {
//Put your code here
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
// Enabling Home button
getActionBar().setHomeButtonEnabled(true);
getActionBar().setDisplayHomeAsUpEnabled(true);
// Setting item click listener for the listview mDrawerList
mDrawerList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedPosition = position;
/* Replace fragment content */
displayView(position);
/* Closing the drawer */
mDrawerLayout.closeDrawer(mDrawerList);
}
});
/* Setting default fragment */
selectedPosition = 0;
displayView(0);
}
private void displayView(int position) {
// update the main content by replacing fragments
android.app.Fragment fragment = null;
Log.i("position", position+"");
switch (position) {
case 0:
fragment = new HomeFragment();
break;
case 1:
fragment = new MessageFragment();
break;
case 2:
fragment = new PreferencesFragment();
break;
case 3:
fragment = new SettingsFragment();
break;
case 4:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);
break;
case 5:
String url = "http://www.example.com";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
break;
default:
break;
}
if (fragment != null) {
android.app.FragmentManager fragmentManager = getFragmentManager();
android.app.FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_frame, fragment);
fragmentTransaction.commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
//setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
}
<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:theme="@android:style/Theme.WithActionBar" >
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer list-->
<ListView
android:id="@+id/drawer_list"
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>
package com.jampez.smalltalk.fragments;
import com.jampez.smalltalk.R;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class HomeFragment extends Fragment {
public HomeFragment(){}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
//getActivity().getActionBar().setTitle(R.string.home);
return rootView;
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:background="#e5e5e5"
android:orientation="vertical" >
<TextView
android:id="@+id/home_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_gravity="start|center_vertical"
android:text="@string/home"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jampez.smalltalk"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="23" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- To auto-complete the email text field in the login form with the user's emails -->
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<application
android:name=".app.AppController"
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<meta-data
android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
<meta-data
android:name="com.facebook.sdk.ApplicationId"
android:value="@string/facebook_app_id" />
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".LoginActivity"
android:label="@string/app_name"
android:windowSoftInputMode="adjustResize|stateHidden" >
</activity>
<activity
android:name="com.facebook.FacebookActivity"
android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
android:label="@string/app_name"
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
</application>
<resources>
<!--
Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
<!--
Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
<item name="android:actionBarStyle">@style/MyActionBar</item>
<item name="android:actionOverflowButtonStyle">@style/MyActionButtonOverflow</item>
<item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">@color/white</item>
</style>
<style name="MyActionButtonOverflow" parent="android:style/Widget.Holo.ActionButton.Overflow">
<item name="android:color">@color/white</item>
</style>
<style name="MyActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">#25a0da</item>
</style>
11-08 19:17:38.618: E/AndroidRuntime(6347): FATAL EXCEPTION: main
11-08 19:17:38.618: E/AndroidRuntime(6347): Process: com.jampez.smalltalk, PID: 6347
11-08 19:17:38.618: E/AndroidRuntime(6347): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jampez.smalltalk/com.jampez.smalltalk.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setTitle(java.lang.CharSequence)' on a null object reference
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2658)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2723)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.ActivityThread.access$900(ActivityThread.java:172)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1422)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.os.Handler.dispatchMessage(Handler.java:102)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.os.Looper.loop(Looper.java:145)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.ActivityThread.main(ActivityThread.java:5832)
11-08 19:17:38.618: E/AndroidRuntime(6347): at java.lang.reflect.Method.invoke(Native Method)
11-08 19:17:38.618: E/AndroidRuntime(6347): at java.lang.reflect.Method.invoke(Method.java:372)
11-08 19:17:38.618: E/AndroidRuntime(6347): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
11-08 19:17:38.618: E/AndroidRuntime(6347): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
11-08 19:17:38.618: E/AndroidRuntime(6347): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setTitle(java.lang.CharSequence)' on a null object reference
11-08 19:17:38.618: E/AndroidRuntime(6347): at com.jampez.smalltalk.MainActivity.onCreate(MainActivity.java:37)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.Activity.performCreate(Activity.java:6221)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
11-08 19:17:38.618: E/AndroidRuntime(6347): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2611)
11-08 19:17:38.618: E/AndroidRuntime(6347): ... 10 more
Upvotes: 6
Views: 4902
Reputation: 1505
Did you try to put getWindow().requestFeature(Window.FEATURE_ACTION_BAR);
in your onCreate()
method? It helped me once. Also try changing theme to Holo
Upvotes: 0
Reputation: 5241
Ok so none of the answers posted have given me much success. I have however managed to get the action bar displayed but with somewhat limited functionality.
The first thing I did was to replace the appcompat_v7
library with android-support-v7-appcompat
. Doing this allows me to call the action bar using getActionBar()
.
The limitation come with trying to control aspects of the action bar. I can set the title and icon fine but if I try to use ActionBarDrawerToggle
I get a NullPointerException
. I also noticed that tapping on the action bar does nothing when normally it opens the drawer.
Upvotes: 0
Reputation: 1825
*First of all include this dependency in your gradle file
compile 'com.android.support:appcompat-v7:22.2.0'
*You should extend your activity to AppCompactActivity and start using toolbar instead of ActionBar.
*This is how you use Toolbar in your MainActivity
public class MainActivity extends AppCompatActivity {
private Toolbar mToolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
}
*this is how to add toolbar in your activity_main.xml
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
local:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
local:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
*your theme should look something like this styles.xml
<style name="MyMaterialTheme" parent="MyMaterialTheme.Base">
</style>
<style name="MyMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
make sure you add this style name in your manifest for your application.
*It will be better if you use v4.app.Fragment rather than using Fragment.
*this is how you should set title from your Fragment class
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle(R.string.home);
Refer this clear Tutorial which will surely help you setting up material Navigation drawer.
If you want to quickly start off without much pain then you can try integrating this third party library.
Upvotes: 7
Reputation: 1745
If you are not getting a ActionBar at all, like visualy, try to rewrite your Activity so you are able to use AppCompatActivity. This thread suggests to use ActionbarActivity instead of FragmentActivity. Since ActionbarActivity is deprecated, AppCompatActivity should work just fine.
For the Nullpointer issue:
Always be consistent with what you are using. If you decide to use AppCompat, make sure you are extending AppCompatActivity. Double check all imports - you might be using the normal Fragment instead of the AppCompat version.
Check your styles and make sure to use AppCompat parents instead of holo ones. That also includes your Actionbar. Instead of Widget.Holo.Light.ActionBar
use parent="@style/Widget.AppCompat.Light.ActionBar"
.
Always call getSupportActionBar
instead of getActionBar()
. Sometimes it might even be neccessary to cast the Activity you are getting with getActivity()
in a Fragment to AppCompatActivity to be sure you are getting the right one: ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("");
.
Upvotes: 0