Home > Back-end >  Navigation won't render fragments
Navigation won't render fragments

Time:12-24

Ive recently started programming in android studio for a school project, and i cant seem to get this bottom navigation working. I've watched multiple video's on how to make a navigation using fragments. The problem is that everytime i try to navigate to a fragment it will make the icon go selected, but it won't render the fragment itself

Menu items
<item android:id="@ id/mainActivity" android:enabled="true" android:icon="@drawable/receipt" android:title=""/> <item android:id="@ id/firstFragment" android:enabled="true" android:icon="@drawable/search" android:title="" />


Main activity

    val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottomNavigationView);
    val navController = findNavController(R.id.fragment)

    bottomNavigationView.setupWithNavController(navController)


Main activity XML

<com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@ id/bottomNavigationView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        app:itemIconTint="@color/black"
        app:itemTextColor="@color/white"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:menu="@menu/menu"/>


    <fragment
        android:id="@ id/fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginEnd="411dp"
        android:layout_marginRight="411dp"
        android:layout_marginBottom="731dp"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@ id/bottomNavigationView"
        app:navGraph="@navigation/my_nav"/> 

Navigation

<activity
    android:id="@ id/mainActivity"
    android:name="nl.bunus.bunusmobileapp.MainActivity"
    android:label="activity_main"
    tools:layout="@layout/activity_main" />
<fragment
    android:id="@ id/firstFragment"
    android:name="nl.bunus.bunusmobileapp.firstFragment"
    android:label="fragment_first"
    tools:layout="@layout/fragment_first" />

CodePudding user response:

Problem

You provide too less important code, but that's why I rebuild your target. And indeed there are some errors occuring. Mostly with dependencies and gradle versions. I think it would be best for all that I provide the whole code as snippets and at the end as project file download.

Solution

GRADLE & DEPENDENCIES

Because of the gradle is important I want to point out that more closly. Your build.gradle("projectname"):

buildscript {
    ext.kotlin_version = '1.3.61'
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:7.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

And also your build.gradle(module) with dependencies:

plugins {
    id 'com.android.application'
    id 'kotlin-android'
    id 'kotlin-android-extensions'
}

android {
    compileSdk 32

    defaultConfig {
        applicationId "com.example.kotlinapplication"
        minSdk 30
        targetSdk 32
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    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'
    }
}

dependencies {

    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.core:core-ktx:1.3.2'
    implementation 'androidx.appcompat:appcompat:1.4.0'
    implementation 'com.google.android.material:material:1.4.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.2'
    testImplementation 'junit:junit:4. '
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
}

ACTIVITY

Let's start with the MainActivity.kt that contains the BottomNavigationView with the loadFragment() method.

Important: Don't forget the binding import shown below!:

import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        title=resources.getString(R.string.fragment1)
        loadFragment(FirstFragment())
        navigationView.setOnNavigationItemSelectedListener {
            when(it.itemId){
                R.id.navigation_appoint-> {
                    title=resources.getString(R.string.fragment1)
                    loadFragment(FirstFragment())
                    return@setOnNavigationItemSelectedListener true
                }

                R.id.navigation_new_appoint-> {
                    title=resources.getString(R.string.second_menu)
                    loadFragment(SecondFragment())
                    return@setOnNavigationItemSelectedListener true
                }

                R.id.navigation_settings-> {
                    title=resources.getString(R.string.third_menu)
                    loadFragment(ThirdFragment())
                    return@setOnNavigationItemSelectedListener true
                }
            }
            false
        }
    }

    private fun loadFragment(fragment: Fragment) {
        val transaction = supportFragmentManager.beginTransaction()
        transaction.replace(R.id.container, fragment)
        transaction.addToBackStack(null)
        transaction.commit()
    }
}

And it's layout activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<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=".MainActivity">

    <FrameLayout
        android:id="@ id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>


    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@ id/navigationView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="0dp"
        android:layout_marginStart="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_navigation" />

</androidx.constraintlayout.widget.ConstraintLayout>

FRAGMENT

Now we have the Activity done there are 3 Fragment left. For simplicity I just post FirstFragment.kt and it's layout fragment_first.xml. You need to do the same for SecondFragment and ThirdFragment of course.

class FirstFragment : Fragment() {
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.fragment_first, container, false)
    }
}

Matching layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FF9800">

    <TextView android:layout_width="match_parent"
              android:layout_centerInParent="true"
              android:textAlignment="center"
              android:textSize="18sp"
              android:text="@string/first_menu"
              android:layout_height="wrap_content"/>
</RelativeLayout>

MENU

Now we are going to create a menu called bottom_navigation.xml in res/menu like this:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@ id/navigation_appoint"
        android:icon="@drawable/ic_menu_black_24dp"
        android:title="@string/fragment1"/>

    <item
        android:id="@ id/navigation_new_appoint"
        android:icon="@drawable/ic_menu_black_24dp"
        android:title="@string/fragment2"/>

    <item
        android:id="@ id/navigation_settings"
        android:icon="@drawable/ic_menu_black_24dp"
        android:title="@string/fragment3"/>

</menu>

STRINGS AND ICON

We need to define the strings for the TextView in strings.xml:

<resources>
    <string name="app_name">KotlinApplication</string>
    <string name="fragment1">Fragment 1</string>
    <string name="fragment2">Fragment 2</string>
    <string name="fragment3">Fragment 3</string>

    <string name="first_menu">First Fragment</string>
    <string name="second_menu">Second Fragment</string>
    <string name="third_menu">Third Fragment</string>
</resources>

And also don't forget to add the icon (here I only used one for all fragments) in res/drawable called ic_menu_black_24dp.


Download Project

You can download the full project BottomNavigationView with 3 Fragments

  • Related