BottomNavigationView 滞后于片段事务
Posted
技术标签:
【中文标题】BottomNavigationView 滞后于片段事务【英文标题】:BottomNavigationView lags on fragment transaction 【发布时间】:2019-02-09 19:51:54 【问题描述】:问题
我在我的一个活动中使用来自 android 设计支持库的 BottomNavigationView
,以及每个导航项的片段。
每次我在栏上选择一个项目时,我都会进行一次片段事务,如下面的 sn-p (为简洁起见,删除了部分代码):
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()
问题是...底栏动画变得超级滞后,只有在片段完全加载并显示在屏幕上后才能完成。
这个问题is not exactly new,因为它也可能在使用导航菜单时发生,但至少可以通过使用DrawerLayout.DrawerListener
解决它,并且只有在抽屉关闭后才执行实际的片段事务。
到目前为止我已经尝试过什么
我尝试“缓存”片段,保留它们的引用以避免每次都重新创建对象(例如MyFragment.newInstance()
),但这不起作用。
我也尝试使用处理程序,这有点解决了问题,但它可能会导致我出现异常in some cases。类似于下面的 sn-p:
handler.postDelayed(changeFragment(fragmentToSet!!), 200)
有没有办法在不使用处理程序(或其他异步调用)的情况下解决此问题,类似于使用导航菜单时this solution 的方式?
【问题讨论】:
【参考方案1】:我通过使用片段管理器隐藏和显示片段来处理这种情况。我写了一个示例代码来处理它,如下所示。
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,
【讨论】:
这确实很有趣!我会实现它并测试它。谢谢! @Mauker:如果它适合你,请接受答案,伙计;) 当然!给我一些,我会回来的。再次感谢。 它解决了 90% 的问题。这是我注意到的:第一次点击导航栏时,它仍然滞后,但在第二次之后它会产生奇迹。我相信如果我改变创建视图的方式,这可以解决。但由于它适用于“第二次点击”,我将其标记为已解决。绝妙的解决方案。 谢谢你。我认为您应该修改与片段视图相关的代码,并尝试通过使用 RecyclerView、ViewStub 等使它们更轻...以上是关于BottomNavigationView 滞后于片段事务的主要内容,如果未能解决你的问题,请参考以下文章
安卓。具有单一活动方法的 BottomNavigationView
BottomNavigationView - 阴影和波纹效果