【问题标题】:How to restore previous scroll position when coming back to fragment after navigating away导航离开后返回片段时如何恢复先前的滚动位置
【发布时间】:2021-09-18 13:39:03
【问题描述】:

我在 Github 有以下项目:https://github.com/AliRezaeiii/News-Cache

首先我在 Fragment 中加载数据,显示来自数据库的数据,然后开始从 API 加载数据。从 API 加载完成后,我会更新数据库,并且 Fragment 中的 recyclerView 也会更新。

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        viewModel.news.observe(viewLifecycleOwner, Observer<List<Article>> { articles ->
            articles?.apply {
                viewModelAdapter.submitList(articles)
            }
        })
    }

这是我的适配器:

class NewsAdapter(val callback: OnClickListener) : ListAdapter<Article, NewsAdapter.NewsViewHolder>(DiffCallback) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = NewsViewHolder.from(parent)

    override fun onBindViewHolder(holder: NewsViewHolder, position: Int) {
        holder.bind(getItem(position), callback)
    }

    /**
     * Allows the RecyclerView to determine which items have changed when the [List] of [Article]
     * has been updated.
     */
    companion object DiffCallback : DiffUtil.ItemCallback<Article>() {
        override fun areItemsTheSame(oldItem: Article, newItem: Article): Boolean {
            return oldItem.url == newItem.url
        }

        override fun areContentsTheSame(oldItem: Article, newItem: Article): Boolean {
            return oldItem == newItem
        }
    }
}

当新数据从 API 到达时,我想滚动到 RecyclerView 的顶部:

handler.postDelayed({
            binding.recyclerView.scrollToPosition(0)
        }, 1000)

问题是当我转到详细信息屏幕并导航回主屏幕时,onActivityCreatedonCreateView 被调用,结果binding.recyclerView.scrollToPosition(0) 也被调用,这不是我想要的。

API 有新数据到达时,滚动到 RecyclerView 顶部的解决方案是什么?

【问题讨论】:

  • 所以当您从另一个活动/片段返回到它时,您希望 recyclerview 保持在相同的滚动位置?
  • 不,当新项目从 API 到达时,我想滚动到位置 0。当我回到主要片段时,保持在同一位置。

标签: android android-recyclerview


【解决方案1】:

你可以很容易地解决这个问题,方法是按住 bool 作为指标 .isFirstLoad

在您开始观察新闻之前在 onActivityCreated 中将其设置为 true,然后在观察者中设置您想要执行的操作。

这样的事情应该可以工作:

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        isFirstNewsFetch = true
        viewModel.news.observe(viewLifecycleOwner, Observer<List<Article>> { articles ->

            articles?.let { articles ->
                viewModelAdapter.submitList(articles)
                if(isFirstNewsFetch) {
                   isFirstNewsFetch = false
                 }else {
                  scrollToTop()
                 }
            }
        })
    }

附注:

apply 标准函数/作用域函数应该用于对象配置。

为您的目的使用let - Kotlin standard functions cheat sheet

【讨论】:

  • 当我启动应用程序(创建应用程序的新实例)时,onActivityCreated 被调用,这意味着 scrollToTop() 永远不会发生。我希望在启动应用程序并且新数据从 API 到达时移动到顶部。
  • 第一次启动应用时你不是已经在顶部了吗?
  • 是的(来自数据库的数据),但是新数据会在几秒钟后从 API 到达,然后我想滚动到顶部。
  • 新数据将触发scrollToTop,因为isFirstNewsFetch 为假。可能我没完全明白你在说什么。
  • 我明白你的意思。让我测试一下,让你知道。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-06
  • 1970-01-01
  • 2022-10-19
  • 2015-12-01
  • 2011-03-02
  • 1970-01-01
相关资源
最近更新 更多