BottomNavigationView отстает от транзакции фрагмента - PullRequest
0 голосов
/ 04 сентября 2018

проблема

Я использую BottomNavigationView из библиотеки поддержки дизайна Android в одном из моих занятий, а также фрагменты для каждого элемента навигации.

Каждый раз, когда я выбираю элемент на панели, я выполняю транзакцию фрагмента, как показано ниже (фрагмент кода был удален для краткости):

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

Проблема в том, что ... Анимация нижней панели становится очень медленной и заканчивается только после полной загрузки фрагмента и его отображения на экране.

Эта проблема не совсем новая , поскольку она также может возникать при использовании меню навигации, но, по крайней мере, ее можно решить с помощью DrawerLayout.DrawerListener и выполнить фактическую транзакцию фрагмента только после ящика закрыто.

Что я пробовал до сих пор

Я пытался «кэшировать» фрагменты, удерживая их ссылки, чтобы избежать повторного создания объектов каждый раз (например, MyFragment.newInstance()), но это не сработало.

Я также пытался использовать обработчики, которые вроде решили проблему, но в некоторых случаях это могло привести к исключению . Нечто похожее на фрагмент ниже:

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

Есть ли способ решить эту проблему без использования обработчиков (или других асинхронных вызовов), аналогично этому решению при использовании меню навигации?

1 Ответ

0 голосов
/ 05 сентября 2018

Я справился с этой ситуацией, скрывая и показывая фрагменты с помощью диспетчера фрагментов. Я написал пример кода, чтобы справиться с ним, как показано ниже.

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

}
...