Search code examples
androidkotlintoolbarandroid-toolbarandroid-architecture-navigation

Null error when attempting to set back button using custom toolbar and navigation components


It's my first time using Navigation components and I'm struggling a bit to set it up with my custom toolbar. I can navigate between views fine but now I'd like to show a back button on the inner views. However, I keep getting Attempt to invoke virtual method 'void androidx.appcompat.app.ActionBar.setTitle(java.lang.CharSequence)' on a null object reference error and not sure what I'm doing wrong please.

MainActivity.kt

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
  
    setSupportActionBar(findViewById(R.id.toolbar))

    val navController = findNavController(this, R.id.nav_host_fragment)

    NavigationUI.setupActionBarWithNavController(this, navController) // NPE happening here
    NavigationUI.setupWithNavController(toolbar, NavHostFragment.findNavController(nav_host_fragment))

}

}

activity_main.xml

<androidx.coordinatorlayout.widget.CoordinatorLayout 
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"
app:layout_behavior="@string/appbar_scrolling_view_behavior">

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <include
        android:id="@+id/toolbarHolder"
        layout="@layout/snippet_toolbar_plain" />

    <androidx.core.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <fragment
            android:id="@+id/nav_host_fragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:navGraph="@navigation/nav_graph" />

    </androidx.core.widget.NestedScrollView>

</LinearLayout>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

snippet_toolbar_plain.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/yellow"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:contentInsetStart="0dp"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

<TextView
    android:id="@+id/tvToolbarTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="Tracker" />

</androidx.appcompat.widget.Toolbar>

Thanks a lot.


Solution

  • When you use

    <include
        android:id="@+id/toolbarHolder"
        layout="@layout/snippet_toolbar_plain" />
    

    The android:id you put here replaces the ID on the root element of your layout/snippet_toolbar_plain element. Therefore findViewById(R.id.toolbar) is returning null - you have no view named toolbar anymore, only the element now named toolbarHolder. This means you don't have an ActionBar set at all (you've set it to null), which is why getSupportActionBar() is returning null and you're getting a NullPointerException.

    You can simply remove the android:id="@+id/toolbarHolder" and your findViewById(R.id.toolbar) will return a non-null Toolbar. Or you can change your findViewById to use R.id.toolbarHolder.