I have an Activity containing a ViewPager that displays N fragments. Each fragment is showing the properties of an object from an ArrayList in my ViewPager's custom adapter (extends FragmentStatePagerAdapter
).
The fragment has (among other things) a button that should remove the currently displayed fragment and scroll to the next one with setCurrentItem(position, true)
so that if the user scrolls back, the previous item is gone. I do so by using something like this (simplified):
deleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
MyActivity parentActivity = (MyActivity)getActivity();
// First, scroll to next item (smoothly)
parentActivity.pager.setCurrentItem(parentActivity.pager.getCurrentItem()+1, true);
// Database stuff...
doSomeDBOperations();
// Method in Activity that removes the current object (I believe this method is working fine and yes, it calls notifyDataSetChanged())
parent.removeObject(currentObject);
}
});
This has the desired behavior as the object represented by the fragment whose delete button was pressed gets removed and the viewpager goes to the next page.
My problem is that the ViewPager doesn't scroll smoothly but rather "jumps instantly" to the next fragment. If I comment the removeObject()
call, the smooth scroll works (but the item isn't removed). I believe it's has something to do with the removeObject()
being called before the setCurrentItem() has finished the smooth scrolling animation?
Any ideas on how to fix this and achieve item removal + smooth scroll? If my assumption is correct, how can I make sure I get the smooth scroll to finish before removing the object?
EDIT 1:
My assumption seems correct. If I put the parent.removeObject(currentObject)
inside
// ...inside the previously shown public void onClick(View v)...
confirm.postDelayed(new Runnable() {
@Override
public void run() {
// Method in Activity that removes the current object (I believe this method is working fine and yes, it calls notifyDataSetChanged())
parent.removeObject(currentObject);
}
}, 1000);
so that the removeObject()
call waits for a second, it works as expected: scroll to the next item, remove the previous. But this is a very ugly workaround so I'd still like a better approach.
EDIT 2:
I figured out a possible solution (see below).
I ended up overriding the
public void onPageScrollStateChanged(int state)
method:
Whenever the user presses the delete button in the fragment, the listener sets a bool in the current item (flagging it for deletion) and scrolls to the next one.
When the onPageScrollStateChanged
detects that the scroll state changed to ViewPager.SCROLL_STATE_IDLE
(which happens when the smooth scroll ends) it checks if the previous item was marked for deletion and, if so, removes it from the ArrayList and calls notifyDataSetChanged()
.
By doing so, I've managed to get the ViewPager to smoothly scroll to the next position and delete the previous item when the "delete" button is pressed.
EDIT: Code snippet.
@Override
public void onPageScrollStateChanged(int state)
{
switch(state)
{
case ViewPager.SCROLL_STATE_DRAGGING:
break;
case ViewPager.SCROLL_STATE_IDLE:
int previousPosition = currentPosition - 1;
if(previousPosition < 0){
previousPosition = 0;
}
MyItem previousItem = itemList.get(previousPosition);
if(previousItem.isDeleted())
{
deleteItem(previousItem);
// deleteItem() Does some DB operations, then calls itemList.remove(position) and notifyDataSetChanged()
}
break;
case ViewPager.SCROLL_STATE_SETTLING:
break;
}
}
Have you tried ViewPager.OnPageChangeListener? I would call removeObject(n) method in OnPageChangeListener.onPageSelected(n+1) method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With