Android: ViewPager2 在创建时设置起始页无效

Android: ViewPager2 setting the starting page on creation not working

我有一个包含两个片段的 viewpager 和一个 viewModel(存储在父 activity 中)保存当前页面可见索引的记录。

这里是父片段的设置:

 override fun setUp() {
    super.setUp()
    titles = arrayOf(R.string.providers, R.string.create_provider)
    fragments = arrayOf(ProvidersListFragment(), CreateProviderFragment())
    pagerAdapter = BaseFragmentAdapter(this, fragments = fragments)
}

override fun setUpViews() {
    super.setUpViews()
    binding.page.adapter = pagerAdapter
    TabLayoutMediator(binding.tabs, binding.page) { tab, position ->
        tab.text = getString(titles[position])
    }.attach()
    binding.page.currentItem = viewModel.currentPage.value!!
}

override fun setUpObservers() {
    super.setUpObservers()
    viewModel.currentPage.observe(viewLifecycleOwner, {
        Log.d(TAG, "setUpObservers: it = $it")
        if (it != binding.page.currentItem)
            binding.page.currentItem = it
    })
}

上面的3个方法都是在onResume().

里面调用的

ViewModel 将记录保存到当前索引,如下所示: var currentPage = MutableLiveData<Int>().apply { value = 1 }

从技术上讲,起始页应该是索引 1,在我的情况下,TabMediator 显示好像选择了第 1 页,但布局显示第 0 页的内容(甚至没有完全加载)。

这就是它显示的内容:

这就是它应该显示的内容:

这是布局 0:

关于此行为的任何想法以及如何避免它?

我通过创建一个导航操作将我直接带到所需的片段页面来解决这个问题。由于这是一种变通方法而不是解决方案,它不能 100% 满足我的需要,当我导航到片段时,它被创建为单个片段而不是页面。

我还在一个具有图像选择器功能的片段中做了一些其他的事情。 问题是当我在第 2 页(创建片段)并尝试 select 图像时,当我完成 selecting 时,我会发现自己在第 1 页。 我所做的是:

在持有寻呼机的片段上:

    override fun setUpObservers() {
        // this method is called inside onResume()
    super.setUpObservers()
    if (binding.page.currentItem != viewModel.page)
        binding.page.currentItem = viewModel.page
    }

关于其他片段:

    override fun onResume() {
    super.onResume()
    productsViewModel.page = 0 //the other fragment set this to 1
     }

视图模型是使用 activity 的主要商店创建的:

private val productsViewModel: ProductsViewModel by viewModels(this::requireActivity)

希望这对遇到同样问题的人有所帮助。

我 运行 遇到了同样的问题,并注意到它与过早设置页面有关(在创建任何片段之前)。所以我需要等待适配器完成创建片段。不幸的是,当适配器完成加载或创建片段时似乎没有回调方法所以我创建了这个子类

inner class TabAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {

    private var finished = false

    // other stuff

    override fun onBindViewHolder(holder: FragmentViewHolder, position: Int, payloads: MutableList<Any>) {
        super.onBindViewHolder(holder, position, payloads)
        if (!finished) {
            finished = true
            // TODO set starting page
        }
    }
}

这不是一个真正干净的解决方案,但它为我完成了工作。