在Android ViewPager中删除项目+滚动到下一步

时间:2013-10-28 19:06:21

标签: android android-fragments android-viewpager fragmentpageradapter

我有一个包含ViewPager的Activity,它显示N个片段。每个片段都在我的ViewPager自定义适配器中的ArrayList中显示对象的属性(扩展FragmentStatePagerAdapter)。

该片段具有(除其他外)一个按钮,该按钮应该删除当前显示的片段并使用setCurrentItem(position, true)滚动到下一个片段,以便在用户向后滚动时,前一个项目消失。我这样做是通过使用这样的(简化):

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

    }
});

这具有所需的行为,因为按下删除按钮的片段所代表的对象将被删除,并且viewpager将转到下一页。

我的问题是ViewPager不能平滑滚动,而是“立即跳转”到下一个片段。如果我评论removeObject()来电,则平滑滚动有效(但该项目未被删除)。我相信它与setCurrentItem()完成平滑滚动动画之前调用的removeObject()有关吗?​​

有关如何解决此问题并实现项目删除+平滑滚动的任何想法?如果我的假设是正确的,我怎样才能确保在删除对象之前完成平滑滚动?

编辑1:

我的假设似乎是正确的。如果我把parent.removeObject(currentObject)放在

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

以便removeObject()调用等待一秒钟,它按预期工作:滚动到下一个项目,删除前一个。但这是一个非常难看的解决方法,所以我仍然想要一个更好的方法。

编辑2:

我找到了一个可能的解决方案(见下文)。

3 个答案:

答案 0 :(得分:12)

我最终压倒了

public void onPageScrollStateChanged(int state) 

方法:

每当用户按下片段中的删除按钮时,监听器在当前项中设置一个bool(标记为删除)并滚动到下一个。

onPageScrollStateChanged检测到滚动状态更改为ViewPager.SCROLL_STATE_IDLE时(在平滑滚动结束时发生),它会检查前一项是否已标记为删除,如果是,则将其从ArrayList并调用notifyDataSetChanged()

通过这样做,我设法让ViewPager顺利滚动到下一个位置,并在按下“删除”按钮时删除上一个项目。

编辑:代码段。

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

}

答案 1 :(得分:1)

你试过ViewPager.OnPageChangeListener吗? 我将在OnPageChangeListener.onPageSelected(n + 1)方法中调用removeObject(n)方法。

答案 2 :(得分:1)

我做了一些与众不同的事情,使工作顺利。想法是删除带有动画的当前项目(将其alpha设置为0),然后将左侧或右侧项目(带有动画)水平平移到现在不可见的项目位置。 动画制作完成后,我将进行实际的数据删除和notfyDataSetChanged()调用。

我将此remove()方法放入ViewPager的子类中

public void remove(int position, OnViewRemovedListener onViewRemovedListener) {

    final int childCount = getChildCount();
    if (childCount > 0) {
        View toRemove = getChildAt(position);
        int to = toRemove.getLeft();

        final PagerAdapter adapter = getAdapter();
        toRemove.animate()
                .alpha(0)
                .setDuration(getResources().getInteger(android.R.integer.config_shortAnimTime))
                .setListener(new SimpleAnimatorListener() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        if (childCount == 1) {
                            if (onViewRemovedListener != null) onViewRemovedListener.onRemoved(position, -1);
                            if (adapter!= null) adapter.notifyDataSetChanged();
                        }
                    }
                })
                .start();

        if (childCount > 1) {
            int newPosition = position + 1 <= childCount - 1 ? position + 1 : position - 1;
            View replacement = getChildAt(newPosition);
            int from = replacement.getLeft();
            replacement.animate()
                    .setInterpolator(new DecelerateInterpolator())
                    .setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime))
                    .translationX(to - from)
                    .setListener(new SimpleAnimatorListener() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            if (onViewRemovedListener != null) onViewRemovedListener.onRemoved(position, newPosition);
                            if (adapter!= null) adapter.notifyDataSetChanged();
                        }
                    })
                    .start();
        }
    }
}

public interface OnViewRemovedListener {

    void onRemoved(int position, int newPosition);
}