【问题标题】:BottomNavigationView reloading fragmentsBottomNavigationView 重新加载片段
【发布时间】:2022-10-12 22:27:03
【问题描述】:

我已经使用 NavController 实现了 BottomNavigationView,但片段会在每次点击时不断重新加载,即使更新了新的导航库。我也试过 setOnNavigationItemReselectedListener 但它不会触发任何东西。我究竟做错了什么 ? 我知道这个问题已经被问过不止一次了,但我觉得我都试过了,但都没有奏效。我希望我可以避免使用旧库或使用样板解决方案来恢复我的代码。 这是我的代码:

build.gradle (:app)

implementation 'androidx.navigation:navigation-runtime-ktx:2.5.2'
implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2'
implementation 'androidx.navigation:navigation-ui-ktx:2.5.2'

家庭活动.kt

class HomeActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener,
Serializable {
private lateinit var binding: ActivityHomeBinding
private lateinit var navController: NavController
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding= ActivityHomeBinding.inflate(layoutInflater)
    setContentView(binding.root)
    val navHostFragment = supportFragmentManager.findFragmentById(R.id.home_container) as NavHostFragment
    navController = navHostFragment.navController
    binding.bottomNavigation.setupWithNavController(navController) 
    }
    }

活动主页.xml

    <RelativeLayout 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:fitsSystemWindows="true"
tools:openDrawer="start"
    tools:context=".HomeActivity">

        <androidx.fragment.app.FragmentContainerView
            android:id="@+id/home_container"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:defaultNavHost="true"
            app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
            app:layout_constraintTop_toBottomOf="@+id/appbar_layout"
            app:navGraph="@navigation/nav_main" />

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@+id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:menu="@menu/bottom_navigation_menu"
            app:layout_constraintTop_toBottomOf="@+id/home_container"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0.5"/>

</RelativeLayout>

nav_main.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/nav_main"
    app:startDestination="@id/firstFragment">

    <fragment
        android:id="@+id/firstFragment"
        android:name="com.projectName.ui.main.ContactsFragment"
        tools:layout="@layout/fragment_contacts" />
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.projectName.SearchFragment"
        android:label="@string/search"
        tools:layout="@layout/search_fragment" />
    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.projectName.ui.main.NotificationsFragment"
        tools:layout="@layout/notifications_fragment" />
    <fragment
        android:id="@+id/fourthFragment"
        android:name="com.projectName.chat.ChatFragment"
        tools:layout="@layout/fragment_main_page" />
</navigation>

bottom_navigation_menu.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/firstFragment"
        android:enabled="true"
        android:icon="@drawable/ic_baseline_contacts_24"
        android:title=""
        app:labelVisibilityMode="unlabeled"/>
    <item
        android:id="@+id/secondFragment"
        android:enabled="true"
        android:icon="@drawable/ic_search_white_24dp"
        android:title=""
        app:labelVisibilityMode="unlabeled"/>
    <item
        android:id="@+id/thirdFragment"
        android:enabled="true"
        android:icon="@drawable/ic_baseline_notifications_none_24"
        android:title=""
        app:labelVisibilityMode="unlabeled"/>
    <item
        android:id="@+id/fourthFragment"
        android:enabled="true"
        android:icon="@drawable/ic_message_white_24dp"
        android:title=""
        app:labelVisibilityMode="unlabeled"/>
</menu>

碎片

class NotificationsFragment : Fragment() {
    companion object {
        fun newInstance() = NotificationsFragment()
    }
    private lateinit var viewModel: NotificationsViewModel
    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        viewModel = ViewModelProvider(this).get(NotificationsViewModel::class.java)
        return inflater.inflate(R.layout.notifications_fragment, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
}

我还给每个布局一个 ID,就像 saveInstateState 的文档所建议的那样。

谢谢你。

编辑

我找不到解决问题的方法,所以我将 BottomNavigationView 与 ViewPager2 一起使用:

HomePagerAdapter.kt

private val TAB_TITLES = arrayOf(
    Constants.CONTACTS,
    Constants.SEARCH,
    Constants.NOTIFICATIONS,
    Constants.CHATS
)

class HomePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
    override fun getItemCount(): Int = TAB_TITLES.size

    override fun createFragment(position: Int): Fragment {
        return if (getPageTitle(position) == Constants.CONTACTS) {
            ContactsFragment.newInstance()
        } else if (getPageTitle(position) == Constants.SEARCH) {
            SearchFragment.newInstance()
        } else if (getPageTitle(position) == Constants.NOTIFICATIONS) {
            NotificationsFragment.newInstance()
        } else {
            ChatsFragment.newInstance()
        }
    }

    private fun getPageTitle(position: Int): String {
        return TAB_TITLES[position]
    }
}

家庭活动.kt

class HomeActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener,
    Serializable, SearchFragment.OnPersonSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_home)

    val homePagerAdapter = HomePagerAdapter(this)
    val viewPager: ViewPager2 = findViewById(R.id.home_view_pager)
    viewPager.adapter = homePagerAdapter
    viewPager.isUserInputEnabled = false
    viewPager.offscreenPageLimit = 1
    viewPager.overScrollMode = ViewPager2.OVER_SCROLL_NEVER

    findViewById<BottomNavigationView>(R.id.bottom_navigation)
        .setOnItemSelectedListener {
            when (it.itemId) {
                R.id.firstFragment -> {
                    viewPager.setCurrentItem(0, false)
                    return@setOnItemSelectedListener true
                }
                R.id.secondFragment -> {
                    viewPager.setCurrentItem(1, false)
                    return@setOnItemSelectedListener true
                }
                R.id.thirdFragment -> {
                    viewPager.setCurrentItem(2, false)
                    return@setOnItemSelectedListener true
                }
                R.id.fourthFragment -> {
                    viewPager.setCurrentItem(3, false)
                    return@setOnItemSelectedListener true
                }
                else -> return@setOnItemSelectedListener false
            }

            }
}
}

活动主页.xml

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/home_view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
 app:layout_constraintBottom_toTopOf="@+id/bottom_navigation"
    app:layout_constraintTop_toBottomOf="@+id/appbar_layout"
 app:layout_behavior="@string/appbar_scrolling_view_behavior" />

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_navigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:menu="@menu/bottom_navigation_menu"
   app:layout_constraintTop_toBottomOf="@+id/home_view_pager"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintHorizontal_bias="0.5"/>

【问题讨论】:

    标签: android kotlin android-fragments bottomnavigationview android-navigation-graph


    【解决方案1】:

    如果我正确理解了您的问题,您希望每当您使用底部导航栏从一个片段更改为另一个片段时,片段将保持其状态。我认为这可能会有所帮助https://developer.android.com/guide/navigation/multi-back-stacks。底部导航上的每个选项卡都有自己的图表,从一个选项卡切换到另一个选项卡时,状态将被保存。让我知道这是否对您有帮助!

    【讨论】:

    • 谢谢,我试过你的链接,但我的片段在每次底部栏点击时不断重新加载......
    • 您介意详细说明“片段正在重新加载”吗?您是在进行 api 调用还是在这些屏幕中发生了什么?
    • 片段状态未保存,所有数据再次加载,就像第一次加载一样。我在片段生命周期中使用了日志来查看会发生什么,并且每次点击底部栏时都会完全重新创建片段,除了从具有良好行为且不重新加载的第一页开始。我不明白为什么,因为它与导航栏的其他三个页面几乎相同
    • 您是否还创建了 3 个嵌套导航图并将它们用于底部导航栏上的每个选项卡?这很奇怪,因为据我记得状态应该持续存在。你介意再试一次并考虑以下几点:medium.com/androiddevelopers/… 或者,你可以创建一个缓存机制数据库或类似的东西,并在刷卡等时刷新数据。
    • 我之前试过你的链接,我重试了,但它仍然是相同的输出..我想我会去旧图书馆
    猜你喜欢
    • 2012-12-15
    • 2018-02-13
    • 2012-11-25
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多