8

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

该片段(除其他外)有一个按钮,该按钮应该删除当前显示的片段并滚动到下一个片段,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()通话进行评论,则平滑滚动会起作用(但不会删除该项目)。我相信这与removeObject()在 setCurrentItem() 完成平滑滚动动画之前被调用有关吗?

关于如何解决这个问题并实现项目移除+平滑滚动的任何想法?如果我的假设是正确的,我如何确保在移除对象之前完成平滑滚动?

编辑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:

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

4

3 回答 3

13

我最终覆盖了

public void onPageScrollStateChanged(int state) 

方法:

每当用户按下片段中的删除按钮时,侦听器都会在当前项目中设置一个布尔值(将其标记为删除)并滚动到下一个项目。

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

}
于 2013-10-29T11:18:40.883 回答
1

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

于 2013-10-28T21:27:17.397 回答
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);
}
于 2018-08-05T04:20:15.953 回答