Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove Item + Scroll to Next in Android ViewPager

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).

like image 943
user1987392 Avatar asked Oct 28 '13 19:10

user1987392


2 Answers

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;
    }

}
like image 59
user1987392 Avatar answered Sep 22 '22 03:09

user1987392


Have you tried ViewPager.OnPageChangeListener? I would call removeObject(n) method in OnPageChangeListener.onPageSelected(n+1) method.

like image 44
Michał Kisiel Avatar answered Sep 23 '22 03:09

Michał Kisiel