You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中点击底部导航栏切换Fragment时显示新内容的问题

Android导航栏切换Fragment不显示的问题修复

问题

使用Android Studio和Kotlin开发应用,InicioActivity页面带有底部导航栏,需求是点击导航栏选项时隐藏当前页面原生控件(TextView、Button、ImageView等)并显示对应Fragment,但目前仅能隐藏原生控件,Fragment无法显示。

现有代码

InicioActivity.kt

class InicioActivity : AppCompatActivity() {
    private lateinit var principianteBoton: Button
    private lateinit var intermedioBoton: Button
    private lateinit var avanzadoBoton: Button
    private lateinit var textView: TextView
    private lateinit var imagenPrincipiante: ImageView
    private lateinit var imagenIntermedio: ImageView
    private lateinit var imagenAvanzado: ImageView
    private lateinit var binding: InicioBinding

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

        setSupportActionBar(binding.toolbar) // Configure the Toolbar as ActionBar

        val navView: BottomNavigationView = binding.navView

        val navController = findNavController(R.id.nav_host_fragment_activity_main)
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)
        principianteBoton = findViewById(R.id.botonPrincipiante)
        intermedioBoton = findViewById(R.id.botonIntermedio)
        avanzadoBoton = findViewById(R.id.botonAvanzado)
        textView = findViewById(R.id.textView)
        imagenPrincipiante = findViewById(R.id.imagenPrincipiante)
        imagenIntermedio = findViewById(R.id.imagenIntermedio)
        imagenAvanzado = findViewById(R.id.imagenAvanzado)

        principianteBoton.setOnClickListener {
            Toast.makeText(this, "Nivel principiante activado.", Toast.LENGTH_SHORT).show()
        }
        intermedioBoton.setOnClickListener {
            Toast.makeText(this, "Nivel intermedio activado.", Toast.LENGTH_SHORT).show()
        }
        avanzadoBoton.setOnClickListener {
            Toast.makeText(this, "Nivel avanzado activado.", Toast.LENGTH_SHORT).show()
        }
        navView.setOnNavigationItemSelectedListener { item ->
            when (item.itemId) {
                R.id.navigation_dashboard, R.id.navigation_notifications -> {
                    // Hide the elements when a navigation item is selected
                    textView.visibility = View.GONE
                    imagenPrincipiante.visibility = View.GONE
                    imagenIntermedio.visibility = View.GONE
                    imagenAvanzado.visibility = View.GONE
                    principianteBoton.visibility = View.GONE
                    intermedioBoton.visibility = View.GONE
                    avanzadoBoton.visibility = View.GONE
                    true
                }
                else -> false
            }
        }
    }
}

关联XML布局

<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:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="60dp"
        android:text="@string/bienvenido"
        app:layout_constraintBottom_toTopOf="@id/imagenPrincipiante"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.498"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.1" />

    <ImageView
        android:id="@+id/imagenPrincipiante"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="96dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.501"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textView"
        app:srcCompat="@drawable/principiante" />

    <Button
        android:id="@+id/botonPrincipiante"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="PRINCIPIANTE"
        app:layout_constraintTop_toBottomOf="@id/imagenPrincipiante"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintVertical_bias="0.3" />

    <ImageView
        android:id="@+id/imagenIntermedio"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:srcCompat="@drawable/intermedio"
        app:layout_constraintTop_toBottomOf="@id/botonPrincipiante"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintVertical_bias="0.4" />

    <Button
        android:id="@+id/botonIntermedio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="INTERMEDIO"
        app:layout_constraintTop_toBottomOf="@id/imagenIntermedio"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintVertical_bias="0.5" />

    <ImageView
        android:id="@+id/imagenAvanzado"
        android:layout_width="100dp"
        android:layout_height="100dp"
        app:srcCompat="@drawable/avanzado"
        app:layout_constraintTop_toBottomOf="@id/botonIntermedio"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintVertical_bias="0.6" />

    <Button
        android:id="@+id/botonAvanzado"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="AVANZADO"
        app:layout_constraintTop_toBottomOf="@id/imagenAvanzado"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintVertical_bias="0.7" />

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        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_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:menu="@menu/bottom_nav_menu" />

    <fragment
        android:id="@+id/nav_host_fragment_activity_main"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintBottom_toTopOf="@id/nav_view"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:titleTextColor="@android:color/white"
        tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>

尝试过的无效代码

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    when (item.itemId) {
        R.id.navigation_dashboard -> {
            Log.d("NAV", "Dashboard selected")
            // Hide the elements when a navigation item is selected
            textView.visibility = View.GONE
            imagenPrincipiante.visibility = View.GONE
            imagenIntermedio.visibility = View.GONE
            imagenAvanzado.visibility = View.GONE
            principianteBoton.visibility = View.GONE
            intermedioBoton.visibility = View.GONE
            avanzadoBoton.visibility = View.GONE
            return true
        }
        R.id.navigation_notifications -> {
            Log.d("NAV", "Notifications selected")
            textView.visibility = View.GONE
            imagenPrincipiante.visibility = View.GONE
            imagenIntermedio.visibility = View.GONE
            imagenAvanzado.visibility = View.GONE
            principianteBoton.visibility = View.GONE
            intermedioBoton.visibility = View.GONE
            avanzadoBoton.visibility = View.GONE
            return true
        }
    }
    return false
}

问题根源

  1. 自定义导航点击事件覆盖默认逻辑:同时使用navView.setupWithNavController(navController)和setOnNavigationItemSelectedListener,后者会覆盖导航组件的默认Fragment切换行为,导致点击导航栏时仅执行隐藏控件的代码,未触发Fragment加载。
  2. 控件引用冗余:同时使用ViewBinding和findViewById,代码冗余且易出错。

修复方案

修改后的InicioActivity.kt

class InicioActivity : AppCompatActivity() {
    private lateinit var binding: InicioBinding

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

        setSupportActionBar(binding.toolbar)

        val navView: BottomNavigationView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_activity_main)
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)

        // 按钮点击事件直接通过ViewBinding访问控件
        binding.botonPrincipiante.setOnClickListener {
            Toast.makeText(this, "Nivel principiante activado.", Toast.LENGTH_SHORT).show()
        }
        binding.botonIntermedio.setOnClickListener {
            Toast.makeText(this, "Nivel intermedio activado.", Toast.LENGTH_SHORT).show()
        }
        binding.botonAvanzado.setOnClickListener {
            Toast.makeText(this, "Nivel avanzado activado.", Toast.LENGTH_SHORT).show()
        }

        // 监听导航目的地变化,动态控制原生控件可见性
        navController.addOnDestinationChangedListener { _, destination, _ ->
            val isHomePage = destination.id == R.id.navigation_home
            // 首页显示原生控件,其他页面隐藏
            binding.textView.visibility = if (isHomePage) View.VISIBLE else View.GONE
            binding.imagenPrincipiante.visibility = if (isHomePage) View.VISIBLE else View.GONE
            binding.imagenIntermedio.visibility = if (isHomePage) View.VISIBLE else View.GONE
            binding.imagenAvanzado.visibility = if (isHomePage) View.VISIBLE else View.GONE
            binding.botonPrincipiante.visibility = if (isHomePage) View.VISIBLE else View.GONE
            binding.botonIntermedio.visibility = if (isHomePage) View.VISIBLE else View.GONE
            binding.botonAvanzado.visibility = if (isHomePage) View.VISIBLE else View.GONE
        }
    }

    // 确保导航返回功能正常
    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_activity_main)
        return navController.navigateUp() || super.onSupportNavigateUp()
    }
}

修复说明

  • 移除自定义导航点击事件:保留setupWithNavController的默认逻辑,确保点击导航栏时正常切换Fragment。
  • 使用导航目的地监听:通过navController.addOnDestinationChangedListener监听页面切换,在不同页面动态控制原生控件的显示/隐藏,逻辑更可靠。
  • 统一使用ViewBinding:删除findViewById代码,直接通过binding访问控件,代码更简洁安全。
  • 完善导航返回逻辑:重写onSupportNavigateUp确保ActionBar的返回按钮正常工作。

内容的提问来源于stack exchange,提问作者Beñat Martínez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 01:02:04