Recyclerview notifyItemMoved不会移动项目

时间:2016-03-15 17:27:44

标签: android android-recyclerview

我想在前面说过我正在重置适配器,因为当调用clearView时我正在对行进行动画处理。在第一次传递时,在我重置适配器之前,notifyItemMoved按预期工作,切换视图。只有在我重置适配器后才会出现问题。

话虽如此,在我用setAdapter()重置适配器之后调用了notifyItemMoved,但是当试图移动一个位置超出它自己的位置时,看起来似乎......“卡住了”。将onMove中的日志记录放入我的ItemTouchHelper中,发现它在尝试移动到另一个位置时每秒都会被调用,就像onChildDraw一样。此外,日志记录显示框架在调用时onMove(RecyclerView recyclerview, ViewHolder source, ViewHolder target) 来源保持不变是有道理的。因此,例如,如果我试图从位置1移动到2源将是1并且目标将是2.但是如果我尝试进一步移动(让我们说位置3),位置1处的视图将不会移动并且源在它开始时停留在1,目标是3.这一直持续到列表的末尾。

是否有理由重置适配器会导致notifyItemMoved不起作用?

以下是代码示例。我删除了实际类和方法的名称以保持匿名。

@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    ViewHolder previousViewHolder;
    ViewHolder nextViewHolder;
    int actualNextPosition =  (recyclerView.getChildAdapterPosition(viewHolder.itemView) + 1) - ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
    int actualPreviousPosition =  (recyclerView.getChildAdapterPosition(viewHolder.itemView) - 1) - ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition();
    if ((Math.abs(mScrolledAmount) / viewHolder.itemView.getHeight() * 100 >= 65)) {

        //We've reached the threshold for dropping a view into its rightful place
        if (mScrolledAmount < 0) {
            //we've dragged up and released
            if (recyclerView.getChildAt(actualPreviousPosition) != null) {
                previousViewHolder = ((ViewHolder) recyclerView
                        .getChildAt(actualPreviousPosition)
                        .getTag());

                TranslateAnimation currentViewAnimator = new TranslateAnimation(0,0, 0, -viewHolder.itemView.getHeight() + Math.abs(mScrolledAmount));
                currentViewAnimator.setDuration(250);
                viewHolder.itemView.startAnimation(currentViewAnimator);

                TranslateAnimation previousViewAnimator = new TranslateAnimation(0,0, 0, viewHolder.itemView.getHeight() - Math.abs(previousViewHolder.itemView.getTranslationY()));
                previousViewAnimator.setDuration(250);
                previousViewHolder.itemView.startAnimation(previousViewAnimator);

                previousViewAnimator.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        LogUtil.d(TAG, "Current Translation" + viewHolder.itemView.getTranslationY() + "PREVIOUS" + previousViewHolder.itemView.getTranslationY());

                        ((Adapter) recyclerView.getAdapter()).resetAdapterAndMakeCall(viewHolder.getAdapterPosition(), previousViewHolder.getAdapterPosition());

                        mViewHasMoved = false;
                        clearAfterAnimate(recyclerView, viewHolder, previousViewHolder);
                        mClearCallback.clearTouch();
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
            }
        }
        else {
            //we've dragged down and released
            if (recyclerView.getChildAt(actualNextPosition) != null) {
                nextViewHolder = ((ViewHolder) recyclerView
                        .getChildAt(actualNextPosition)
                        .getTag());

                //((Adapter) recyclerView.getAdapter()).resetAdapterAndMakeCall(viewHolder.getAdapterPosition(), nextViewHolder.getAdapterPosition());

                TranslateAnimation currentViewAnimator = new TranslateAnimation(0,0, 0, viewHolder.itemView.getHeight() - mScrolledAmount);
                currentViewAnimator.setDuration(250);
                viewHolder.itemView.startAnimation(currentViewAnimator);

                TranslateAnimation nextViewAnimator = new TranslateAnimation(0,0, 0, -viewHolder.itemView.getHeight() + Math.abs(nextViewHolder.itemView.getTranslationY()));
                nextViewAnimator.setDuration(250);
                nextViewHolder.itemView.startAnimation(nextViewAnimator);
                nextViewAnimator.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {

                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {

                        //LogUtil.d(TAG, "Current Translation" + viewHolder.itemView.getTranslationY() + "PREVIOUS" + nextViewHolder.itemView.getTranslationY());
                        ((Adapter) recyclerView.getAdapter()).resetAdapterAndMakeCall(viewHolder.getAdapterPosition(), nextViewHolder.getAdapterPosition());

                        mViewHasMoved = false;
                        clearAfterAnimate(recyclerView, viewHolder, nextViewHolder);
                        mClearCallback.clearTouch();

                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {

                    }
                });
            }
            //Translate Animation positive translates up negative translates down
        }
    }
    else if ((Math.abs(mScrolledAmount) / viewHolder.itemView.getHeight() * 100 < 65)) {
        if (mScrolledAmount < 0) {
            //dragged up and released
            TranslateAnimation currentViewAnimator = new TranslateAnimation(0,0, mScrolledAmount, 0);
            currentViewAnimator.setDuration(250);
            currentViewAnimator.setFillAfter(true);
            viewHolder.itemView.startAnimation(currentViewAnimator);
        }
        else {
            //dragged down and released
            TranslateAnimation currentViewAnimator = new TranslateAnimation(0,0, mScrolledAmount, 0);
            currentViewAnimator.setDuration(250);
            currentViewAnimator.setFillAfter(true);
            viewHolder.itemView.startAnimation(currentViewAnimator);
        }
        super.clearView(recyclerView, viewHolder);

        if (recyclerView.getChildAt(actualPreviousPosition) != null) {
            previousViewHolder = ((ViewHolder) recyclerView
                    .getChildAt(actualPreviousPosition)
                    .getTag());
            if (previousViewHolder.itemView != null) {
                super.clearView(recyclerView, previousViewHolder);
            }
        }

        if (recyclerView.getChildAt(actualNextPosition) != null) {
            nextViewHolder = ((ViewHolder) recyclerView
                    .getChildAt(actualNextPosition)
                    .getTag());
            if (nextViewHolder.itemView != null) {
                super.clearView(recyclerView, nextViewHolder);
            }
        }
    }

    LogUtil.d(TAG, "Cleared");

    viewHolder.itemView.setAlpha(ALPHA_FULL);

    if (viewHolder instanceof ItemTouchHelperViewHolder) {
        // Tell the view holder it's time to restore the idle state
        ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
        // I have this if the user lifts their finger up and they've moved to another position or
        mHandler.postDelayed(() -> {
            if (mViewHasMoved) {
                mClearCallback.clearTouch();
                mViewHasMoved = false;
            }
        }, 250);
        itemViewHolder.onItemClear();
    }
}

@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
    if (source.getItemViewType() != target.getItemViewType()) {
        return false;
    }
    // Notify the adapter of the move

    LogUtil.d(TAG, Integer.toString(source.getAdapterPosition()) + Integer.toString(target.getAdapterPosition()));
    mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
    super.clearView(recyclerView, target);
    mViewHasMoved = true;
    return true;
}

//In a fragment
public void resetAdapterAndMakeCall(int fromPosition, int toPosition, List<Data> data) {
    LinearLayoutManager manager = (LinearLayoutManager) recyclerview.getLayoutManager();
    int firstItem = manager.findFirstVisibleItemPosition();
    View firstItemView = manager.findViewByPosition(firstItem);
    float topOffset = firstItemView.getTop();
    mAdapter = new Adapter(getActivity(), data, this);
    recycler.setAdapter(adapter);

    manager.scrollToPositionWithOffset(firstItem, (int) topOffset);
}

@Override
public boolean onItemMove(int fromPosition, int toPosition) {
    Collections.swap(list, fromPosition, toPosition);
    // The problem with doing a swap here for like order is that the adapter starts the position from 0
    // and we need to send the position to the server without a 0.
    notifyItemMoved(fromPosition, toPosition);
    mViewHasMoved = true;
    return true;
}

0 个答案:

没有答案
相关问题