导航不会呈现片段

Navigation won't render fragments

我最近开始在 android 工作室为学校项目编程,但我似乎无法使用底部导航。我看过多个关于如何使用片段进行导航的视频。问题是,每次我尝试导航到一个片段时,它都会让图标被选中,但它不会呈现片段本身

菜单项
<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="" />


主要activity

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

    bottomNavigationView.setupWithNavController(navController)


主要 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"/> 

导航

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

问题

你提供的代码太不重要了,但这就是我重建你的目标的原因。确实发生了一些错误。主要是依赖项和 gradle 版本。我认为最好将整个代码作为片段提供,最后作为项目文件下载。

解决方案

GRADLE & 依赖项

因为 gradle 很重要,所以我想更详细地指出这一点。你的 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
}

还有你的 build.gradle(module) 依赖项:

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

让我们从包含 BottomNavigationViewloadFragment() 方法的 MainActivity.kt 开始。

重要:不要忘记下面显示的binding import!:

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()
    }
}

它的布局 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>

片段

现在我们已经 Activity 完成了,还剩下 3 Fragment 个。为简单起见,我只是 post FirstFragment.kt 和它的布局 fragment_first.xml。当然,您需要对 SecondFragmentThirdFragment 执行相同的操作。

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

匹配布局:

<?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>

菜单

现在我们要在 res/menu 中创建一个名为 bottom_navigation.xmlmenu,如下所示:

<?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.xml中为TextView定义字符串:

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

并且不要忘记在 res/drawable 中添加图标(这里我只为所有片段使用一个)名为 ic_menu_black_24dp


下载项目

您可以下载完整的项目here(主办方:Workupload)


结果

最后我们有一个 BottomNavigationView 可以在其项目中导航 3 Fragments