当前位置: 首页 > 知识库问答 >
问题:

BottomNavigationView滞后于片段事务

佴淮晨
2023-03-14

我在我的一个活动中使用了Android设计支持库中的BottomNavigationView,以及每个导航项的片段。

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

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

问题是...底部栏动画变得超级滞后,只有在片段完全加载并显示在屏幕上后才会完成。

这个问题并不完全是新问题,因为在使用导航菜单时也会发生,但至少可以通过使用抽屉布局来解决。DrawerListener,只有在抽屉关闭后才执行实际的片段事务。

我试图缓存片段,保持它们的引用以避免每次都重新创建对象(例如MyFragment.new实例()),但这不起作用。

我还尝试使用处理程序,这在某种程度上解决了问题,但在某些情况下可能会导致异常。类似下面的代码片段:

html" target="_blank">handler.postDelayed({changeFragment(fragmentToSet!!)}, 200)

在使用导航菜单时,有没有一种方法可以在不使用处理程序(或其他异步调用)的情况下以类似于此解决方案的方式解决此问题?

共有1个答案

公子昂
2023-03-14

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

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

}
 类似资料:
  • 问题内容: 我正在使用带有底部导航视图的简单应用程序。我有3个带有文本的片段,我想在Botton Navigation中选择一个项目时启动它们,但是我不知道在MainActivity.java中写什么。所有片段都具有.xml布局和.java。我搜索了一些代码,写了代码,搜索了视频,但没有成功。 我正在学习Fragments和UI Dynamic,因此我在Android Studio中使用“底部导航

  • 此时,Frag2在堆栈上,是唯一可见的片段。我使用了replace和addToBackStack,因为我需要后退导航。我的问题是,当我在Frag2内旋转屏幕时,活动中的super.oncreate(savedInstanceState)方法调用frag1的构造函数。 在用户按下后退按钮之前,有没有什么方法可以避免调用Frag1的构造函数?

  • 在我的应用程序的主要活动中,我有BottomNavigationView和四个项目/选项卡。每个选项卡都有自己的片段。我使用Jetpack导航组件在这些片段之间导航。 当我使用导航到另一个片段时,以前的片段视图正在被销毁。我的一个片段包含地图视图,这使得片段视图的创建操作繁重。当用户更改BottomNavigationView选项卡时,在使用地图视图导航到片段时,旧的Android手机上有明显的延

  • 这是我第一次尝试开发android应用程序。 我有一个带有ConstraintLayout的MainActivity,它具有BottomNavigationView。每当选择第一个导航项时,我想显示一个类别列表(显示在片段中),然后每当选择此类别时,将显示与该特定类别相关的另一个列表(显示在另一个片段中)。 我读到(Android-fragment.replace()不替换内容-将其放在顶部)它指

  • 我目前正在开发一个应用程序使用Android Studio与静态编程语言。 此应用程序有一个BottomNavigationView和4个片段。 我的问题是如何使用BottomNavigationView仅显示片段区域? 代码如下: fragment.xml activity_main.xml Android Studio: 3.3.2

  • 问题内容: 我在此DataBricks帖子中看到,SparkSql支持窗口函数,特别是我正在尝试使用lag()窗口函数。 我有几行信用卡交易,并且已经对它们进行了排序,现在我要遍历各行,并为每一行显示交易金额,以及当前行金额与上一行金额的差额。 在DataBricks帖子之后,我提出了这个查询,但是它给我抛出了一个异常,我无法理解为什么。 这是在PySpark中。tx是我在注册为临时表时创建的数据