1

Problem: Fragment is not changed to next fragment
Condition: Using BottomNavigationView, Navigation component and multi-module app
Action:

  1. launch app on emulator
  2. when launched app, home fragment will be shown
  3. when tapped message icon or my page icon, the fragment is not changed

My Inspection: I debugged the application when tapped the ic ons to change fragment, in NavController.java

        NavDestination newDest = navigator.navigate(node, finalArgs,
                navOptions, navigatorExtras);

returns the expected fragment, but the fragment does not change...

Project Structure:

  • app
    • layout
      • activity_main.xml
  • core
    • navigation
      • navigation.xml
    • menu
      • menu.xml
  • features
    • home
      • fragment_home.xml
    • message
      • fragment_message.xml
    • mypage
      • fragment_my_page.xml

Code:
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/container">

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/nav_view"
            app:menu="@menu/bottom_nav_menu" />

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

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

bottom_nav_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/navigation_home"
        android:icon="@drawable/ic_dashboard_black_24dp"
        android:title="@string/title_home"
        android:enabled="true"/>

    <item
        android:id="@+id/navigation_message"
        android:icon="@drawable/ic_notifications_black_24dp"
        android:title="@string/title_message"
        android:enabled="true"/>

    <item
        android:id="@+id/navigation_mypage"
        android:icon="@drawable/ic_notifications_black_24dp"
        android:title="@string/title_mypage"
        android:enabled="true" />
</menu>

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

    <fragment
        android:id="@+id/navigation_home"
        android:name="app.home.HomeFragment"
        android:label="@string/title_home" />

    <fragment
        android:id="@+id/navigation_message"
        android:name="app.message.MessageFragment"
        android:label="@string/title_message"/>

    <fragment
        android:id="@+id/navigation_mypage"
        android:name="app.mypage.MyPageFragment"
        android:label="@string/title_mypage" />

</navigation>

MainActivity.kt

class MainActivity : AppCompatActivity() {
    private val binding: ActivityMainBinding by lazy {
        DataBindingUtil.setContentView<ActivityMainBinding>(
            this,
            R.layout.activity_main
        )
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val navView: BottomNavigationView = binding.navView
        val navHostFragment =  supportFragmentManager.findFragmentById(R.id.nav_host_fragment)  as NavHostFragment
        navView.setupWithNavController(navHostFragment.navController)
        navView.setOnNavigationItemSelectedListener { item:MenuItem ->
            Log.d("main", "setOnNavigationItemSelectedListener " + item)
            navHostFragment.navController.navigate(item.itemId)
            true
        }
    }

build.gradle(app)

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: "androidx.navigation.safeargs"

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"
    repositories {
        google()
    }

    defaultConfig {
        applicationId "app"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        flavorDimensions "default"
        productFlavors {
            develop {
                applicationIdSuffix ".develop"
            }
            staging {
                applicationIdSuffix ".staging"
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }

    buildFeatures{
        dataBinding = true
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    //
    implementation project(":core")
    implementation project(":features:home")
    implementation project(":features:message")
    implementation project(":features:mypage")
    //
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.0'
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'com.google.android.material:material:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation 'androidx.navigation:navigation-fragment:2.2.2'
    implementation 'androidx.navigation:navigation-ui:2.2.2'
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.2.2'
    implementation 'androidx.navigation:navigation-ui-ktx:2.2.2'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.recyclerview:recyclerview:1.1.0'
    implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

}

When I tried to create activity from BottomNavigationView of Android Studio's template, it worked well. However I tried to separated into multi-module app, it doesn't work well.

any advice??

anizo
  • 237
  • 4
  • 14
  • Is there a particular reason you're calling `setOnNavigationItemSelectedListener` right after `setupWithNavController()`? That is overriding the `OnNavigationItemSelectedListener` set by `setupWithNavController()`. – ianhanniballake Jul 05 '20 at 18:55
  • When I call `setupWithNavController` first, `OnNavigationItemSelected` is not called. – anizo Jul 05 '20 at 21:43
  • You don't need to call `setOnNavigationItemSelectedListener` at all if you're using `setupWithNavController()`. – ianhanniballake Jul 05 '20 at 21:48
  • hmm... I just remove `setOnNavigationItemSelectedListener` but still fragment is not changed. Fragment is actually generated but display is not changed... – anizo Jul 05 '20 at 23:06
  • 1
    Finally, I found a solution. In my each fragments has a constant value but the key is not constraint so that fragments show same value even if the fragment is switched. – anizo Jul 07 '20 at 11:23

0 Answers0