Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
707 views
in Technique[技术] by (71.8m points)

navigation componets: BottomNavigationView and navigationDrawer, In a project android

Good morning, any recommendations to use, navigation componets: BottomNavigationView and NavigationDrawer, In a project android.

This project was based on the Samples for Android Architecture Components repository. This is the repository where I took it out: https://github.com/mackgaru/architecture-components-samples/tree/main/NavigationAdvancedSample

When clicking on a NavigationDrawer item, the navigation does not work well or the app crashes.

This is my repo, if you want to give me a hand: https://github.com/mackgaru/nBottom_nDrawer.git

Thank you so much.

BottonNavigationView, NavigationDrawer

Here is the error

Process: com.cocktapp.cocktapp, PID: 27899
    java.lang.IllegalArgumentException: Navigation action/destination com.cocktapp.cocktapp:id/action_navigation_home_to_homeDetalleFragment cannot be found from the current destination Destination(com.cocktapp.cocktapp:id/homeDetalleFragment) label=Detalle class=com.cocktapp.cocktapp.ui.home.HomeDetalleFragment
        at androidx.navigation.NavController.navigate(NavController.java:938)
        at androidx.navigation.NavController.navigate(NavController.java:875)
        at androidx.navigation.NavController.navigate(NavController.java:861)
        at androidx.navigation.NavController.navigate(NavController.java:849)
        at com.cocktapp.cocktapp.ui.MainActivity.onNavigationItemSelected(MainActivity.kt:95)
        at com.google.android.material.navigation.NavigationView$1.onMenuItemSelected(NavigationView.java:217)
        at androidx.appcompat.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:834)
        at androidx.appcompat.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:158)
        at androidx.appcompat.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:985)
        at com.google.android.material.internal.NavigationMenuPresenter$1.onClick(NavigationMenuPresenter.java:416)
        at android.view.View.performClick(View.java:5646)
        at android.view.View$PerformClick.run(View.java:22473)
        at android.os.Handler.handleCallback(Handler.java:761)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:156)
        at android.app.ActivityThread.main(ActivityThread.java:6517)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

MainActivity

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    private var currentNavController: LiveData<NavController>? = null
    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding
    private lateinit var drawerLayout: DrawerLayout

    private lateinit var viewModelHome: HomeViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        if (savedInstanceState == null) {
            setupBottomNavigationBar()
        }
        setSupportActionBar(binding.includeMainContent.toolbarActivity)
        drawerLayout = binding.drawerLayout
        val navigationView: NavigationView = binding.navView
        val toogle = ActionBarDrawerToggle(this, drawerLayout, binding.includeMainContent.toolbarActivity, R.string.open_navigation, R.string.close_navigation)
        drawerLayout.addDrawerListener(toogle)
        toogle.syncState()
        navigationView.setNavigationItemSelectedListener(this)

    }//fin onCreate

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        setupBottomNavigationBar()
    }

    private fun setupBottomNavigationBar() {
        val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
        val navGraphIds = listOf(R.navigation.navigation_home, R.navigation.navigation_add, R.navigation.navigation_card, R.navigation.navigation_pay, R.navigation.navigation_config)

        // Setup the bottom navigation view with a list of navigation graphs
         val controller = bottomNavigationView.setupWithNavController(
            navGraphIds = navGraphIds,
            fragmentManager = supportFragmentManager,
            containerId = R.id.nav_host_container,
            intent = intent
        )
        // Whenever the selected controller changes, setup the action bar
        controller.observe(this, Observer { navController ->
            setupActionBarWithNavController(navController)
        })
        currentNavController = controller
        Log.i("controller", "valor es = ${currentNavController!!.value}");
    }

    override fun onSupportNavigateUp(): Boolean {
        Log.i("controller", "support = ${currentNavController?.value?.navigateUp()}");
        val navController = findNavController(R.id.nav_host_container)
        //return currentNavController?.value?.navigateUp() ?: false
        return navController.navigateUp(appBarConfiguration)  || super.onSupportNavigateUp()
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        return super.onOptionsItemSelected(item)
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        if(item.itemId == R.id.nav_camera){
            Toast.makeText(this , "Camera Click", Toast.LENGTH_SHORT).show()
            //Navigation.findNavController(this, R.id.navigationHome).navigate(R.id.action_navigation_home_to_homeDetalleFragment)
            currentNavController?.value?.navigate(R.id.action_navigation_home_to_homeDetalleFragment)
            drawerLayout.closeDrawer(Gravity.LEFT)
        }
        return true;
    }

    override fun onBackPressed() {
        if(drawerLayout.isDrawerOpen(Gravity.LEFT)){
            drawerLayout.closeDrawer(Gravity.LEFT)
        }else{
            super.onBackPressed()
        }
    }

}

activity_main.xml

<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:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawer_layout"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        android:id="@+id/include_main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        layout="@layout/dra_main_content_appbar"/>

    <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/dra_drawer_nav_header"
        app:menu="@menu/drawer_navigation" />

</androidx.drawerlayout.widget.DrawerLayout>

dra_main_content_appbar

<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=".ui.MainActivity">

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

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar_activity"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.Cocktapp.PopupOverlay" />

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

    <include layout="@layout/dra_content" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

dra_content

<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/dra_main_content_appbar">

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

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/bottom_nav"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

</androidx.constraintlayout.widget.ConstraintLayout>

Each element of the BottonNavigationView has a different navigation file: example: navigation_home

    <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/navigationHome"
        app:startDestination="@id/navigation_home">
    
        <fragment
            android:id="@+id/navigation_home"
            android:name="com.cocktapp.cocktapp.ui.home.HomeFragment"
            android:label="Home"
            tools:layout="@layout/fragment_home" >
            <action
                android:id="@+id/action_navigation_home_to_homeDetalleFragment"
                app:destination="@id/homeDetalleFragment" />
        </fragment>
        <fragment
            android:id="@+id/homeDetalleFragment"
            android:name="com.cocktapp.cocktapp.ui.h

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

All you have to do is:

  override fun onNavigationItemSelected(item: MenuItem): Boolean {
        if(item.itemId == R.id.nav_camera){
            Toast.makeText(this , "Camera Click", Toast.LENGTH_SHORT).show()
            if(currentNavController.currentDestination.id != R.id.homeDetalleFragment){
                currentNavController?.value?.navigate(R.id.action_navigation_home_to_homeDetalleFragment)
            }
            drawerLayout.closeDrawer(Gravity.LEFT)
        }
        return true;
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...