Компонент навигации: не удается найти NavController

Я использую компонент навигации для навигации в моем приложении. Он отлично работает внутри фрагментов, но не может найти хост навигации в действии, который содержит фактический хост навигации.

Я пытаюсь открыть новый фрагмент, когда пользователь нажимает на FAB, который я включил в XML основного действия. Когда я вызываю findNavController (), он не может найти контроллер. Контроллер узла навигации находится в формате XML. Я не могу понять, почему не находит.

Основная деятельность

class MainActivity : AppCompatActivity(), OnActivityComponentRequest {
    override fun getTabLayout(): TabLayout {
        return this.tabLayout
    }

    override fun getFap(): FloatingActionButton {
        return this.floatingActionButton
    }

    private lateinit var tabLayout: TabLayout
    private lateinit var floatingActionButton: FloatingActionButton

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)
        this.tabLayout = tabs
        this.floatingActionButton = fab

        fab.setOnClickListener {

         it.findNavController().navigate(R.id.addNewWorkoutFragment)

        }
    }
}

Основной XML активности

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
        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"
        tools:context=".domain.MainActivity"
        android:animateLayoutChanges="true">

    <com.google.android.material.appbar.AppBarLayout
            android:layout_height="wrap_content"
            android:layout_width="match_parent"
            android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:layout_scrollFlags="scroll|enterAlways"
                app:popupTheme="@style/AppTheme.PopupOverlay"/>

        <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

            <com.google.android.material.tabs.TabItem
                    android:text="Test 1"
                    android:layout_height="match_parent"
                    android:layout_width="match_parent"/>

            <com.google.android.material.tabs.TabItem
                    android:text="Test 2"
                    android:layout_height="match_parent"
                    android:layout_width="match_parent"/>
        </com.google.android.material.tabs.TabLayout>

    </com.google.android.material.appbar.AppBarLayout>

      <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:navGraph="@navigation/main_navigation" />


    <com.google.android.material.bottomappbar.BottomAppBar
            android:id="@+id/bar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"/>


    <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_anchorGravity="right|top"
            app:layout_anchor="@+id/bar"
            android:src="@drawable/ic_add_black_24dp"/>

</androidx.coordinatorlayout.widget.CoordinatorLayout>

person Jeremi    schedule 23.12.2018    source источник
comment
I can't understand why it fails to find it. возвращает null?   -  person Anmol    schedule 23.12.2018
comment
Да, возвращает ноль. Мне удалось найти решение. Я поставлю это как ответ, чтобы было удобнее читать   -  person Jeremi    schedule 23.12.2018
comment
Navigation.findNavController( this, R.id.nav_host) .navigate(R.id.addNewWorkoutFragment) Попробуйте использовать это должно работать   -  person Anmol    schedule 23.12.2018
comment
Я тоже пробовал это, но это не сработало. Я опубликовал свое решение.   -  person Jeremi    schedule 23.12.2018
comment
Можете ли вы попробовать настроить OnClickListener в onStart() активности и проверить. ваше решение похоже на взлом.   -  person Anmol    schedule 23.12.2018
comment
Вы правы, установка onClickListener в onStart () сработала :) Спасибо   -  person Jeremi    schedule 23.12.2018
comment
Я отправлю это как ответ. Принимаю.   -  person Anmol    schedule 23.12.2018
comment
Конечно, приму :)   -  person Jeremi    schedule 23.12.2018


Ответы (8)


Попробуйте настроить кнопку onClickListener of Fab в onStart Activity, поскольку в onCreate Activity просто раздувает View и не устанавливает NavHostController. Поэтому, если вы настроите onClickListener в onStart of activity, все будет работать должным образом.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    setSupportActionBar(toolbar)
    this.tabLayout = tabs
    this.floatingActionButton = fab
  }

override fun onStart() {
    super.onStart()
    floatingActionButton.setOnClickListener {
      it.findNavController().navigate(R.id.addNewWorkoutFragment)
    }
  }
person Anmol    schedule 23.12.2018
comment
Теперь у SOF есть функция благодарности рядом с ответом, и вы можете ее использовать. : P в любом случае твой WC @KhamidjonKhamidov - person Anmol; 13.07.2020
comment
да, в onCreate () он разбился, но в onStart () он работает правильно. - person Mehmet Gür; 16.06.2021

В Java вы можете найти NavController внутри активности следующим образом:

Navigation.findNavController(this,R.id.nav_host).navigate(R.id.YourFragment);
person JunaidKhan    schedule 03.12.2019

Я получал такое же исключение, пока мне не удалось получить navController следующим образом:

val navHostFragment = supportFragmentManager.findFragmentById(R.id.my_fragment_container_view_id) as NavHostFragment
val navController = navHostFragment.navController

Получено из этого ответа:

Прежде чем найти контроллер навигации, вам необходимо установить представление, если вы используете привязку:

binding = BaseLayoutBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)

Если не:

setContentView(R.layout.activity_main)

Используйте соответствующую привязку для фрагментов.

person LightMan    schedule 19.08.2020
comment
Это фактически то, что указано в документации по компонентам навигации: developer.android.com / guide / navigation / При создании NavHostFragment с помощью FragmentContainerView или при ручном добавлении NavHostFragment к вашей активности через FragmentTransaction, попытка получить NavController в onCreate () Activity через Navigation.findNavController (Activity, @IdRes int ) не удастся. Вместо этого вы должны получить NavController непосредственно из NavHostFragment. - person Socram; 23.03.2021
comment
Before finding the nav controller, you need to set the view вот что мне помогло. - person lasec0203; 23.06.2021

Оказывается, эта активность, которая содержит контроллер навигации ... не имеет компонента навигации.

Решение состоит в том, чтобы вручную настроить NavController для каждого представления, содержащегося в действии.

val navController = findNavController(R.id.nav_host_fragment)
Navigation.setViewNavController(fab, navController)

Теперь это сработает:

fab.setOnClickListener {

    it.findNavController().navigate(R.id.addNewWorkoutFragment)

}

Я до сих пор не понимаю, почему это работает так, как это работает, поэтому любые объяснения будут более чем приветствоваться :)

На данный момент Android API просто не имеет особого смысла.

Источник: Перейдите к фрагменту при нажатии FAB (компоненты архитектуры навигации) < / а>

person Jeremi    schedule 23.12.2018

вы все еще можете получить доступ к своему oncreate, выполнив

    //the id would be the id of the Fragment Element In Your Activity XML File
    val navGraph = Navigation.findNavController(this, R.id.activity_main)
    binding.mainFab.setOnClickListener {
        navGraph.navigate(R.id.destinationFragment)
    }
person Peterstev Uremgba    schedule 21.04.2020

Проблема может заключаться в том, что FAB был добавлен к действию или фрагменту, отличному от того, который используется фрагментом NavHost. В этом случае, когда вы вызываете it.findNavController(), он не может найти контроллер навигации.

Вы можете либо проверить, что ваш FAB принадлежит фрагменту, извлеченному NavHost, либо вызвать Activity findNavController(<id>) и передать ему идентификатор фрагмента, который вы ищете.

override fun onCreate(savedInstanceState: Bundle?) {
        ...
        fab.setOnClickListener {
            findNavController(R.id.nav_host_fragment)
                .navigate(R.id.addNewWorkoutFragment)

        }
    }
person Slava Senchenko    schedule 09.09.2019

Я нашел этот ответ полезным. В своей деятельности вставьте этот код

Navigation.findNavController(this, R.id.nav_host_fragment).navigate(R.id.yourDestination)
person lvl3ha    schedule 24.11.2020

Это версия расширения для Kotlin:

 fun AppCompatActivity.findNavController(
    @IdRes navHostViewId: Int
): NavController {
    val navHostFragment =
        supportFragmentManager.findFragmentById(navHostViewId) as NavHostFragment

    return navHostFragment.navController
}

navHostViewId - это идентификатор вашего androidx.fragment.app.FragmentContainerView.

person Mohsents    schedule 30.06.2021