【问题标题】:Saving scroll of RecyclerView with navigation component使用导航组件保存 RecyclerView 的滚动
【发布时间】:2020-04-13 11:28:03
【问题描述】:

我在我的应用程序中使用带有 BottomNavigationView 的导航组件。它在 4 个目的地之间切换,其中一个包含一个带有 RecyclerView 的片段,其中包含数百个项目。当我使用后退按钮时,RecyclerView 会恢复到之前的滚动位置。但是当我使用 BottomNavigationView 在目的地之间切换时,它不会恢复到以前的位置并重置到 RecyclerView 的顶部。这是我试图阻止的代码

    override fun onPause() {
    super.onPause()

    lastScrollPos = linearLayoutManager.findFirstVisibleItemPosition()
    }

    override fun onResume() {
        super.onResume()

        card_recyclerView.layoutManager?.scrollToPosition(lastScrollPos)
}

这行不通 将 RecyclerView 恢复到正确位置的最佳方法是什么?

【问题讨论】:

    标签: android kotlin android-recyclerview


    【解决方案1】:

    它不滚动到上一个位置的原因是navController在与bottomNavigation一起使用时重新创建了片段(使用替换)。

    保存滚动状态的一种简单方法是将layoutManager 状态存储在onDestroyView 中并将其恢复到onCreateView,与scrollToPosition 不同,此方法将滚动到确切位置,当NavController 重新创建片段。

    我在另一个线程https://stackoverflow.com/a/66940957/2102794发布了完整代码

    【讨论】:

      【解决方案2】:

      这可以通过将ScrollView 的Y 轴位置保存在成员变量中并在onCreateView() 中恢复来完成。这是有效的,因为成员变量没有被破坏。

      class DiscoverDataFragment : BaseFragment() {
          private var loaded = false
          private var scrollPos = 0
          
          override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
              return inflater.inflate(R.layout.fragment_discover_data, container, false)
          }
          
          override fun onCreateBind() {
              super.onCreateBind()  
              if (!loaded) {
                  // Load views here
                  loaded = true
              }
              
              if (scrollPos > 0) {
                  scrollDiscoverData.scrollY = scrollPos
              }
          
              setScrollListener()
          }
          
          private fun setScrollListener() {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                  scrollDiscoverData.setOnScrollChangeListener { v, scrollX, scrollY, oldScrollX, oldScrollY ->
                  scrollPos = scrollY
              }
          }
      }
      

      【讨论】:

        【解决方案3】:

        你必须在片段生命周期之外初始化适配器,例如

        class MyFragment : Fragment() {
        
        private val myViewModel by viewModel<MyViewModel>()
        private lateinit var myAdapter : MyAdapter
        
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            myAdapter = MyAdapter()
            Log.d("checkListData", myAdapter.currentList.toString())
            myViewModel.someListData.observe(viewLifecycleOwner){ listData ->
                myAdapter.submitList(listData)
            }
        }}
        

        【讨论】:

        • 哦,普通人。先学Android框架。这是一种反模式,因为它是一个很大的内存泄漏。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-05
        • 1970-01-01
        • 1970-01-01
        • 2019-11-28
        • 1970-01-01
        • 2020-02-20
        • 1970-01-01
        相关资源
        最近更新 更多