This question already has answers here:
FragmentContainerView using findNavController
(9 answers)
Closed 2 years ago.
I try to write an Android app which uses the Navigation Component from androidx, a toolbar and a drawer layout to slide in a setting menu from the left. I followed the guides Get started with the Navigation component and tried to add a top app bar and a setting using this guide Update UI components with NavigationUI.
When my apps starts, the following exception is thrown:
java.lang.IllegalStateException: Activity ....MainActivity#e686cd8 does not have a NavController set on 2131230993
Side remark: If I open nav_graph.xml in design mode, the hosts pane reports "No NavHostFragments found. This nav graph must be referenced from a NavHostFragment in a layout in order to be accessible." Maybe this error and the exception are related and share the same root cause. However, my navigation graph is referenced by a NavHostFragment though, see below.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="#+id/main_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="?attr/actionBarTheme" />
<androidx.fragment.app.FragmentContainerView
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/nav_graph" />
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="#menu/drawer_view"
app:headerLayout="#layout/nav_header" />
</androidx.drawerlayout.widget.DrawerLayout>
This layout
contains a FragmentContainerView
references #navigation/nav_graph (pasted below)
contains a NavigationView
references #layout/nav_header (pasted below)
references #menu/drawer_view (pasted below)
nav_header.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.widget.LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="192dp"
android:background="?attr/colorPrimaryDark"
android:gravity="bottom"
android:padding="16dp"
android:theme="#style/ThemeOverlay.AppCompat.Dark">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/app_name"
android:textAppearance="#style/TextAppearance.AppCompat.Body1" />
</android.widget.LinearLayout>
drawer_view.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="#+id/nav_home"
android:icon="#drawable/ic_home"
android:title="#string/home"/>
<item
android:id="#+id/nav_settings"
android:icon="#drawable/ic_settings"
android:title="#string/settings" />
</group>
</menu>
fragment_home.xml:
<?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"
tools:context=".HomeFragment"/>
This fragment is referenced by nav_graph (pasted below) as the home fragment (start destination).
nav_graph.xml:
<?xml version="1.0" encoding="utf-8"?>
<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/nav_graph"
app:startDestination="#id/homeFragment">
<fragment
android:id="#+id/homeFragment"
android:name="de.mhnnet.lychee4android.HomeFragment"
android:label="fragment_home"
tools:layout="#layout/fragment_home" />
</navigation>
MainActivity.java:
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_main );
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment );
AppBarConfiguration appBarConfiguration =
new AppBarConfiguration.Builder(navController.getGraph()).build();
Toolbar toolbar = findViewById( R.id.main_toolbar );
NavigationUI.setupWithNavController( toolbar, navController, appBarConfiguration );
}
Further Remarks:
I already found some tips which says that androidx.fragment.app.FragmentContainerView should be replaced by fragment. However, this feels wrong as the linter recommends to use FragmentContainerView instead of fragment and the official Android docs use FragmentContainerView, too.
Okay to get Nav Controller in your activity either replace your
<androidx.fragment.app.FragmentContainerView
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/nav_graph" />
with
<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/nav_graph" />
But as the lint suggest to change fragment with FragmentContainerView Use the below code to get Nav Controller in your activity.
NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment);
if (navHostFragment != null) {
NavController navController = navHostFragment.getNavController();
// Setup NavigationUI here
}
Related
I have nav host fragment and bottom navigation view inside home fragment as below
<androidx.constraintlayout.widget.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="home.HomeFragment2">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/homeNavHost"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/bottomMenu"
app:layout_constraintEnd_toEndOf="parent"
app:navGraph="#navigation/staging_menu_navigation1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomMenu"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_menu" />
</androidx.constraintlayout.widget.ConstraintLayout>
The menu as
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/staging_dashboard_nav_graph"
android:icon="#drawable/ic_home"
android:title="#string/menu_dashboard" />
<item
android:id="#+id/staging_offer_nav_graph"
android:icon="#drawable/ic_offer"
android:title="#string/menu_offers" />
<item
android:id="#+id/staging_profile_nav_graph"
android:icon="#drawable/ic_profile"
android:title="#string/menu_profile" />
</menu>
The navigation graph as
<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/staging_menu_navigation"
app:startDestination="#id/dashboardFragment3">
<include app:graph="#navigation/staging_dashboard_nav_graph" />
<include app:graph="#navigation/staging_offer_nav_graph" />
<include app:graph="#navigation/staging_profile_nav_graph" />
<fragment
android:id="#+id/dashboardFragment3"
android:name="com.octave.dashboard.DashboardFragment"
android:label="DashboardFragment" />
</navigation>
The other graphs are as
<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/staging_dashboard_nav_graph"
app:startDestination="#id/dashboardFragment">
<fragment
android:id="#+id/dashboardFragment"
android:name="com.octave.dashboard.DashboardFragment"
android:label="dashboard_fragment"
tools:layout="#layout/dashboard_fragment" />
</navigation>
Offer 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/staging_offer_nav_graph"
app:startDestination="#id/offersFragment">
<fragment
android:id="#+id/offersFragment"
android:name="com.octave.offers.OffersFragment"
android:label="offers_fragment"
tools:layout="#layout/offers_fragment" />
</navigation>
Profile 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/staging_profile_nav_graph"
app:startDestination="#id/profileFragment">
<fragment
android:id="#+id/profileFragment"
android:name="com.octave.profile.ProfileFragment"
android:label="profile_fragment"
tools:layout="#layout/profile_fragment" />
In my home fragment I am setting up as
binding.bottomMenu.setupWithNavController(Navigation.findNavController(requireActivity(), R.id.homeNavHost))
When I tap on bottom menu items the fragment doesn't change.
What is wrong over here?
If you are trying to create another nav graph with the bottom navigation bar that is already a part of the default nav graph, you first need to change the defaultNavHost value to false in XML of wherever your nav host fragment is in. then find NavHost to get NavController:
val navHost = childFragmentManager.findFragmentById(R.id.${yourNavHostFragment} as NavHostFragment
val navController = navHost.navController
view.findViewById<BottomNavigationView>(R.id.bottomNavigationView).setupWithNavController(navController!!)
I'm running into a wall debugging what should be a simple issue: I have an app with one activity, which contains a navigation graph, which should display a fragment on start. But it isn't.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
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=".MainActivity"
>
<androidx.fragment.app.FragmentContainerView
android:id="#+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="#navigation/nav_graph"/>
</FrameLayout>
res/navigation/nav_graph.xml
<?xml version="1.0" encoding="utf-8"?>
<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/nav_graph"
app:startDestination="#id/listFragment"
>
<fragment
android:id="#+id/listFragment"
android:name="org.example.my_app.ui.ListFragment"
android:label="fragment_list"
tools:layout="#layout/fragment_list"
>
<action
android:id="#+id/action_listFragment_to_detailFragment"
app:destination="#id/detailFragment"
/>
</fragment>
<fragment
android:id="#+id/detailFragment"
android:name="org.example.my_app.ui.DetailFragment"
android:label="fragment_detail"
tools:layout="#layout/fragment_detail"
/>
</navigation>
fragment_list.xml
<?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"
tools:context=".ui.ListFragment"
>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="This should be visible"
/>
</FrameLayout>
ListFragment.kt
class ListFragment : Fragment(R.layout.fragment_list)
Despite this dead-simple setup, I see a blank screen (just an app bar) and debug listeners added to the ListFragment class init don't ever get called. Why isn't my navGraph initializing an instance of the fragment?
Documentation:
NavHostFragment provides an area within your layout for self-contained navigation to occur.
You are missing to declare the fragment placeholder as a NavHostFragment in the FragmentContainerView via the android:name attribute; and therefore the navigation won't occur.
<androidx.fragment.app.FragmentContainerView
....
android:name="androidx.navigation.fragment.NavHostFragment"
I'm trying to create a BottomNavigationBar in my Android app, and I keep getting this error:
Cannot resolve method 'setupWithNavController(com.google.android.material.bottomnavigation.BottomNavigationItemView, androidx.navigation.NavController)'
Not sure what I'm doing wrong since these 3 lines of code in the activity are found in many nav bar guides online.
Activity Code Segment in Question
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigation);
BottomNavigationItemView bottomNavigationView = findViewById(R.id.bottomNavigationView);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupWithNavController(bottomNavigationView, navController); //cannot resolve this
}
Relevant Dependencies
implementation "androidx.navigation:navigation-fragment:2.3.1"
implementation "androidx.navigation:navigation-ui:2.3.1"
activity_navigation.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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=".NavigationActivity">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="#android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_nav_menu" />
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_graph" />
</androidx.constraintlayout.widget.ConstraintLayout>
bottom_nav_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/settingsNavFragment"
android:icon="#drawable/ic_baseline_settings_24"
android:title="Settings" />
<item
android:id="#+id/homeNavFragment"
android:icon="#drawable/ic_baseline_home_24"
android:title="Home" />
<item
android:id="#+id/groupsNavFragment"
android:icon="#drawable/ic_baseline_groups_24"
android:title="Groups" />
</menu>
nav_graph.xml
<?xml version="1.0" encoding="utf-8"?>
<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/nav_graph"
app:startDestination="#id/homeNavFragment">
<fragment
android:id="#+id/homeNavFragment"
android:name="com.example.foodwithfriends.HomeNavFragment"
android:label="fragment_home_nav"
tools:layout="#layout/fragment_home_nav" />
<fragment
android:id="#+id/settingsNavFragment"
android:name="com.example.foodwithfriends.settingsNavFragment"
android:label="fragment_settings_nav"
tools:layout="#layout/fragment_settings_nav" />
<fragment
android:id="#+id/groupsNavFragment"
android:name="com.example.foodwithfriends.GroupsNavFragment"
android:label="fragment_groups_nav"
tools:layout="#layout/fragment_groups_nav" />
</navigation>
You've casted your BottomNavigationView incorrectly.
Replace
BottomNavigationItemView bottomNavigationView = findViewById(R.id.bottomNavigationView);
With
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
Just check u import right library. U need to add AndroidX library.
Cant understanding why it's not working...
another analog project bnv working correctly...
in-app app:startDestination="#+id/navigate_hot" work correctly, but on click bnv items - nothing happens
mainActivity.XML
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bttm_nav"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/white"
android:elevation="4dp"
app:itemIconSize="35dp"
app:itemTextColor="#color/bnv_tab_item_foreground"
app:itemIconTint="#color/bnv_tab_item_foreground"
app:layout_constraintBottom_toBottomOf="parent"
app:menu="#menu/bottom_nav_menu"/>
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<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/bnv_navigation" />
MainActivity.kt
override fun onSupportNavigateUp(): Boolean {
return findNavController(this#ActivityMain,R. id.nav_host_fragment).navigateUp()
}
private fun setupNavigation() {
val navController = findNavController(this#ActivityMain, R.id.nav_host_fragment)
bttm_nav.setupWithNavController(navController)
}
bnv_navigation.XML
<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/nav_graph"
app:startDestination="#+id/navigate_hot">
<fragment
android:id="#+id/navigate_news"
android:name="com.example.fatsale.fragments.NewsFragment"
android:label="News"
tools:layout="#layout/fragment_news" />
<fragment
android:id="#+id/navigate_hot"
android:name="com.example.fatsale.fragments.HotFragment"
android:label="Collection"
tools:layout="#layout/fragment_hot" />
<fragment
android:id="#+id/navigate_profile"
android:name="com.example.fatsale.fragments.ProfileFragment"
android:label="Profile"
tools:layout="#layout/fragment_profile" />
</navigation>
tell this dunkey what need to do..
In your menu file for bottomnavigationview, each item id has to same as fragment id which is added in navigation graph xml file. Also in menu file, Each item has to give OrderInCategory for fragment position no in bottomnavigationview.
I m new in android ,i had search many example which is related from navigation drawer and I also apply to our project but the last things that
In my project Humberger icon and navigation view(slide) are not work properly and humberger icon doesn't show .
I apply onCreatePost()
And many method apply such as configuration and other but there is not a solution.so how can I fix this problem.. in my system install Androidx
I had the same issue and I fixed it by adding the navigation graph into the Hosted Fragment, I'll post the layout code from the main view.
main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
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/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!-- This layout contains the Action App Bar see the app_bar_main.xml code-->
<include
layout="#layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- This is the Navigation drawer widget, Which opens when you click on the hamburger icon -->
<!-- For that you could add header view -->
<!-- Can add menu or custom view for navigation tabs -->
<com.google.android.material.navigation.NavigationView
android:id="#+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main">
<include layout="#layout/nav_body_main"/>
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
app_bar_main.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:id="#+id/root_landing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".ui.landing.main.MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
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="#android:color/transparent"
app:layout_collapseMode="pin"
app:popupTheme="#style/AppTheme.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<include layout="#layout/content_main" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
content_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_main">
<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:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/mobile_navigation"/>
<!-- This navigation graph will sort the issue -->
</androidx.constraintlayout.widget.ConstraintLayout>
And find the Activity Code.
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow,
R.id.nav_tools, R.id.nav_share, R.id.nav_send)
.setDrawerLayout(drawer)
.build();
navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController)
Easiest Way
The easiest way is to generate the code through the Android Studio since you are new.
RightClick on the Package folder -> New -> Activity -> Gallery
from that select Navigation Drawer Activity
Cheers!