本文介绍了BottomNavigationView滞后于片段事务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的一个活动中使用了Android设计支持库中的BottomNavigationView,同时为每个导航项使用了片段.

I'm using the BottomNavigationView from the Android Design Support Library on one of my Activities, alongside with Fragments for each navigation item.

每次我在栏上选择一个项目时,我都会进行片段交易,如下面的代码片段(为简洁起见,删除了部分代码):

Each time I select an item on the bar, I do a fragment transaction, like the snippet below (some parts of the code was removed for brevity):

private var fragmentToSet: Fragment? = null

private val onNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->

    fragmentToSet = when (item.itemId) {
        // Choose fragment based on selection
        // ...
    }

// ...

supportFragmentManager.beginTransaction()
                .replace(R.id.container, fragmentToSet)
                .commit()
}

问题是...底部小节动画超级滞后,只有在片段完全加载并显示在屏幕上之后才能结束.

The problem is... The bottom bar animation gets super laggy, and only finishes after the fragment is fully loaded and displayed on the screen.

此问题不是完全新的,因为使用导航菜单时也可能发生这种情况,但是至少可以使用DrawerLayout.DrawerListener来解决它,并且只有在抽屉关闭后才进行实际的Fragment事务.

This issue is not exactly new since it can also happen while using the Navigation Menu, but at least it's possible to solve it by using the DrawerLayout.DrawerListener and do the actual Fragment transaction only after the drawer is closed.

我试图缓存"这些片段,保留它们的引用以避免每次都重新创建对象(例如MyFragment.newInstance()),但这是行不通的.

I tried to "cache" the fragments, holding their reference to avoid recreating the objects every time (e.g. MyFragment.newInstance()), but that didn't work.

我也尝试使用处理程序,这可以解决问题,但可能导致我出现异常在某些情况下.类似于以下代码段:

I also tried to use handlers, which kinda solved the problem, but it might lead me to an exception in some cases. Something like the snippet below:

handler.postDelayed({changeFragment(fragmentToSet!!)}, 200)

有没有一种方法可以使用此解决方案而无需使用处理程序(或其他异步调用)来解决此问题在使用导航菜单时?

Is there a way to solve this issue without using handlers (or other async calls), on a similar fashion to this solution while using the Navigation Menu?

推荐答案

我通过使用片段管理器隐藏和显示片段来处理这种情况.我编写了一个示例代码来处理它,如下所示.

I handled this situation by hiding and showing fragments using fragment manager. I wrote a sample code to deal with it as below.

class MainActivity : BaseActivity() {

    private val homeFragment = HomeFragment.newInstance()
    private val categoryFragment = CategoryFragment.newInstance()
    private val searchFragment = SearchFragment.newInstance()

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

        navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener)
        navigation.menu.findItem(R.id.navigation_home).isChecked = true

        supportFragmentManager.beginTransaction()
                .add(R.id.containerFrameLayout, homeFragment)
                .add(R.id.containerFrameLayout, categoryFragment)
                .add(R.id.containerFrameLayout, searchFragment)
                .commit()
        setTabStateFragment(TabState.HOME).commit()
    }

    override fun onBackPressed() {
        if (supportFragmentManager.backStackEntryCount > 0 || !homeFragment.isHidden) {
            super.onBackPressed()
        } else {
            setTabStateFragment(TabState.HOME).commit()
            navigation.menu.findItem(R.id.navigation_home).isChecked = true
        }
    }

    private fun setTabStateFragment(state: TabState): FragmentTransaction {
        supportFragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE)
        val transaction = supportFragmentManager.beginTransaction()
        transaction.setCustomAnimations(R.anim.fragment_enter, R.anim.fragment_exit)
        when (state) {
            TabState.HOME -> {
                transaction.show(homeFragment)
                transaction.hide(categoryFragment)
                transaction.hide(searchFragment)
            }
            TabState.CATEGORY -> {
                transaction.hide(homeFragment)
                transaction.show(categoryFragment)
                transaction.hide(searchFragment)
            }
            TabState.SEARCH -> {
                transaction.hide(homeFragment)
                transaction.hide(categoryFragment)
                transaction.show(searchFragment)
            }
        }
        return transaction
    }

    private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
        when (item.itemId) {
            R.id.navigation_home -> {
                setTabStateFragment(TabState.HOME).commit()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_category -> {
                setTabStateFragment(TabState.CATEGORY).commit()
                return@OnNavigationItemSelectedListener true
            }
            R.id.navigation_search -> {
                setTabStateFragment(TabState.SEARCH).commit()
                return@OnNavigationItemSelectedListener true
            }
        }
        false
    }

    internal enum class TabState {
        HOME,
        CATEGORY,
        SEARCH,
    }

}

这篇关于BottomNavigationView滞后于片段事务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 03:19