I
I
Ilya Kolpakov2021-04-23 08:07:06
Android
Ilya Kolpakov, 2021-04-23 08:07:06

Why is the NavController not showing up?

Error:
java.lang.IllegalStateException: View android.widget.FrameLayout{32a4e29 VE..... ......ID 0,0-0,0} does not have a NavController set

My Navigation Graph:

<navigation 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/navigation_main_graph"
    app:startDestination="@id/noteListFragment">

    <fragment
        android:id="@+id/noteListFragment"
        android:name="com.kivinus.notee.fragments.NoteListFragment"
        android:label="fragment_note_list"
        tools:layout="@layout/fragment_note_list" >
        <action
            android:id="@+id/action_noteList_to_noteDetail"
            app:destination="@id/noteDetailFragment" />
    </fragment>

    <fragment
        android:id="@+id/noteDetailFragment"
        android:name="com.kivinus.notee.fragments.NoteDetailFragment"
        android:label="fragment_note_detail"
        tools:layout="@layout/fragment_note_detail" >
        <action
            android:id="@+id/action_noteDetail_to_noteList"
            app:destination="@id/noteListFragment" />
    </fragment>

</navigation>


The XML of the start fragment I want to navigate from:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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="@color/light_yellow"
    tools:context=".fragments.NoteListFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/noteRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</FrameLayout>


Fragment code (here I don’t understand how to use Navigation)
(I make a variable navController and in onCreateView I try to assign Navigation.findNavController(fragmentView) to it):
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController
import androidx.navigation.Navigation
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.kivinus.notee.NoteListFragmentViewModel
import com.kivinus.notee.R
import com.kivinus.notee.localDatabase.NoteEntity


class NoteListFragment : Fragment() {

    private fun quickToast(content: String) {
        Toast.makeText(context, content, Toast.LENGTH_SHORT).show()
    }

    private val viewModel by lazy {
        ViewModelProvider(this).get(NoteListFragmentViewModel::class.java)
    }

    private lateinit var noteRecyclerView: RecyclerView
    private var noteAdapter: NoteAdapter = NoteAdapter()
    private lateinit var navigationController: NavController


override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val fragmentView = inflater.inflate(R.layout.fragment_note_list, container, false)
        noteRecyclerView = fragmentView.findViewById(R.id.noteRecyclerView)
        noteRecyclerView.layoutManager = LinearLayoutManager(context)
        noteRecyclerView.adapter = noteAdapter
        navigationController = Navigation.findNavController(fragmentView)
        return fragmentView
    }


    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        viewModel.noteListLiveData.observe(viewLifecycleOwner, { notes ->
            updateUI(notes)
        })
    }


    private inner class NoteHolder(view: View) :
        RecyclerView.ViewHolder(view), View.OnClickListener {

        private lateinit var note: NoteEntity

        init {
            itemView.setOnClickListener(this)
        }

        //      find required views
        private val titleTextView: TextView = itemView.findViewById(R.id.note_title)
        private val textContentTextView: TextView = itemView.findViewById(R.id.note_text_content)

        //      binding
        fun bind(note: NoteEntity) {
            this.note = note
            this.titleTextView.text = note.title
            this.textContentTextView.text = note.textContent
        }


        override fun onClick(v: View) {
            navigationController.navigate(R.id.action_noteList_to_noteDetail)
        }
    }


    private fun updateUI(notes: List<NoteEntity>?) {
        quickToast(notes.toString())
        noteAdapter.submitList(notes)
    }


    private inner class NoteAdapter :
        ListAdapter<NoteEntity, NoteHolder>(DiffCallback()) {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NoteHolder {
            val view = layoutInflater.inflate(R.layout.list_item_note, parent, false)
            return NoteHolder(view)
        }

        override fun onBindViewHolder(holder: NoteHolder, position: Int) {
            holder.bind(getItem(position))
        }
    }

    class DiffCallback : DiffUtil.ItemCallback<NoteEntity>() {
        override fun areItemsTheSame(oldItem: NoteEntity, newItem: NoteEntity): Boolean {
            return oldItem.id == newItem.id
        }

        override fun areContentsTheSame(oldItem: NoteEntity, newItem: NoteEntity): Boolean {
            return oldItem == newItem
        }
    }

}


I've been trying to figure out why this is happening for hours (never worked with a Navigation Component before)
Thanks in advance.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
I
Ilya Kolpakov, 2021-04-26
@kivinus1

The error turned out to be just stupid - the Navigation Controller was simply not installed on the Activity, and I didn’t even doubt it and looked for the error in the fragment / XML code.
It's a pity that someone had to take the time to look at the question

F
foonfyrick, 2021-04-24
@foonfyrick

val navController=Navigation.findNavController(this,R.id. navigation_main_graph )
Your example is slightly different from mine, mine was like this:

<fragment
        android:id="@+id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        fab:defaultNavHost="false"
        fab:navGraph="@navigation/nav_graph" />

open class MainActivity : AppCompatActivity() {
    private lateinit var navController:NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //creating backArrow
        navController=Navigation.findNavController(this,R.id.fragment)
        NavigationUI.setupActionBarWithNavController(this,navController)
    }
    override fun onSupportNavigateUp(): Boolean {
        return navController.navigateUp()
    }

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question