0

I have a FragmentPagerAdapter (tabFragmentAdapter) with 4 tabs, or fragments. Every fragment has a RecyclerView with adapter. Ever holder is a list of cards that has a remove button.

When I press the remove button, the card gets deleted from the current fragment:

adapter?.notifyDataSetChanged()

But the problem is that I want the card to be removed in every tab. But when I swipe to the right, it is still there in the second tab but not in the third and fourth tab.

When I override getItemPosition and return POSITION_NONE:

override fun getItemPosition(fragment: Any): Int {
    // POSITION NONE, so that it reloads every time.
    return POSITION_NONE
}

I have the same problem and I see a little visible screen yank.

When I swipe back from the fourth position to the first, the second tab is updated and displayed correctly.

One solution is to call:

tabFragmentAdapter?.notifyDataSetChanged()

But this makes the list to briefly disappear and be shown again. This is not a nice effect.

When I add addOnTabSelectedListener, the App hangs up.

    val tabs: TabLayout = findViewById(R.id.tabs)
    tabs.setupWithViewPager(viewPager)
    tabs.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
        override fun onTabSelected(tab: TabLayout.Tab?) {
            Log.d("","")
        }

        override fun onTabUnselected(tab: TabLayout.Tab?) {
            Log.d("","")
            tabFragmentAdapter?.notifyDataSetChanged()
        }

        override fun onTabReselected(tab: TabLayout.Tab?) {
            Log.d("","")
        }
    })

I tried this SO answer

Jim Clermonts
  • 1,694
  • 8
  • 39
  • 94

2 Answers2

0

In FragmentPageAdapter the adjacent fragments of the currently visible one are active, the view is created. When you change something in the current fragment you notify the view of this fragment, that something changed and the view updates itself.

The adjacent fragments don't know of these changes, you have to notify them somehow,with the code provided I have no idea how you can do it. I Personally would use a viewmodel which is tied to the activity and every fragment accesses this viewmodel and starts observing the data in their onResume and updates the view, when something changes.

The fragments which are not adjacent to the current one are stopped and the view is created when it becomes an adjacent fragment of the current one. When the view is created you get a view of the current data state, also updating the view you had before.

I hope this helps you, to find a solution how and when to update your view.

Dominik Wuttke
  • 535
  • 1
  • 4
  • 12
  • I've posted my solution. the ViewModel triggers a method in MainActivity and this passes the index and the to be removed item. Not perfect but it works. – Jim Clermonts Mar 06 '21 at 23:25
0

Here is my fix. It works but could be better.

class TabFragmentAdapter(fragmentManager: FragmentManager,
                         private val tabFragments: List<VersesFragment>) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

    fun refresh(verse: Verse, index: Int) {
        if (index == 0 && tabFragments.size > 1) {
            // First one
            tabFragments[index+1].adapter?.removeCorrectItem(verse)
            tabFragments[index+1].adapter?.notifyDataSetChanged()

        } else if (index == (tabFragments.size-1) && tabFragments.size > 1) {
            // Last one
            tabFragments[index-1].adapter?.removeCorrectItem(verse)
            tabFragments[index-1].adapter?.notifyDataSetChanged()

        } else if (index > 0 && index < tabFragments.size) {
            tabFragments[index - 1].adapter?.removeCorrectItem(verse)
            tabFragments[index - 1].adapter?.notifyDataSetChanged()

            tabFragments[index + 1].adapter?.removeCorrectItem(verse)
            tabFragments[index + 1].adapter?.notifyDataSetChanged()
        }
    }
}
Jim Clermonts
  • 1,694
  • 8
  • 39
  • 94