android view.scrollBy 干扰拖动侦听器事件

问题描述

我正在尝试使用 DragShadowBuilder

实现滚动

但是当我的 scrollBy 拖动事件调用 LOCATION 时,所有其他拖动事件都会延迟到视图滚动后的一段时间

特别是它们在滚动开始后延迟 1 秒到 4 秒

如果我不调用 scrollBy 那么我的事件会立即收到但我的视图不会滚动

我尝试使用 scrollBy 调用 ViewCompat.postOnAnimation 但这没有任何区别

我也尝试从单独的线程调用它,但这没有任何区别

虽然我必须使用 smoothScrollBy,因为 scrollBy 会抛出 not UI thread 异常

有谁知道我如何在滚动时解决这种响应滞后的问题?

因为我的要求是

  1. 我的视图必须可以拖动到 RecyclerView 之外的其他视图(并且能够与这些视图交互)

  2. 我的视图必须能够在被拖动时滚动回收器视图,使其位置位于回收器视图的底部或顶部

这是我当前的代码

// based on androidx.recyclerview.widget.ItemTouchHelper source code

int startedX;
int startedY;
ViewHolder mSelected;
ShadowItemTouchHelper itemTouchHelper;
private Rect mTmpRect;
private long mDragScrollStartTimeInMs;
RecyclerView mRecyclerView;
Callback mCallback;
float x;
float y;

final Runnable mScrollRunnable = new Runnable() {
    @Override
    public void run() {
        if (mSelected != null && scrollIfNecessary()) {
            mRecyclerView.removeCallbacks(mScrollRunnable);
            ViewCompat.postOnAnimation(mRecyclerView,this);
        }
    }
};

boolean scrollIfNecessary() {
    if (mSelected == null) {
        mDragScrollStartTimeInMs = Long.MIN_VALUE;
        return false;
    }
    final long now = System.currentTimeMillis();
    RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();
    if (mTmpRect == null) {
        mTmpRect = new Rect();
    }
    int scrollX = 0;
    int scrollY = 0;
    lm.calculateItemDecorationsForChild(mSelected.itemView,mTmpRect);
    if (lm.canScrollHorizontally()) {
        int width = mRecyclerView.getMeasuredWidth();
        if (width - x < 200) {
            scrollX = (int) (mSelected.itemView.getWidth() * 0.2);
        } else if (width - x > width - 200) {
            scrollX = (int) (-mSelected.itemView.getWidth() * 0.2);
        }
    }
    if (lm.canScrollVertically()) {
        int height = mRecyclerView.getMeasuredHeight();
        if (height - y < 200) {
            scrollY = (int) (mSelected.itemView.getHeight() * 0.2);
        } else if (height - y > height - 200) {
            scrollY = (int) (-mSelected.itemView.getHeight() * 0.2);
        }
    }
    if (scrollX != 0 || scrollY != 0) {
        if (mDragScrollStartTimeInMs == Long.MIN_VALUE) {
            mDragScrollStartTimeInMs = now;
        }

        // SCROLL
        mRecyclerView.scrollBy(scrollX,scrollY);

        return true;
    }
    mDragScrollStartTimeInMs = Long.MIN_VALUE;
    return false;
}

@Override
public boolean onDrag(View v,DragEvent event) {
    //noinspection unchecked
    Pair<ShadowItemTouchHelper,ViewHolder> data = (Pair<ShadowItemTouchHelper,ViewHolder>) event.getLocalState();

    final int action = event.getAction();
    switch(action) {
        case DragEvent.ACTION_DRAG_STARTED:
            toastList.show(dragStartedKey);
            Log.d(TAG,"onDrag: STARTED");
            itemTouchHelper = data.first;
            mRecyclerView = itemTouchHelper.mRecyclerView;
            mCallback = itemTouchHelper.mCallback;
            mSelected = data.second;
            startedX = mSelected.itemView.getLeft();
            startedY = mSelected.itemView.getTop();
            return true;
        case DragEvent.ACTION_DRAG_ENTERED:
            toastList.show(dragEnteredKey);
            Log.d(TAG,"onDrag: ENTERED");
            mSelected = data.second;
            return true;

        case DragEvent.ACTION_DROP:
            toastList.show(dragDropKey);
            Log.d(TAG,"onDrag: DROP");
            mSelected = null;
            return true;
        case DragEvent.ACTION_DRAG_ENDED:
            toastList.show(dragEndedKey);
            Log.d(TAG,"onDrag: ENDED");
            mSelected = null;
            return true;
        case DragEvent.ACTION_DRAG_EXITED:
            toastList.show(dragExitedKey);
            Log.d(TAG,"onDrag: EXITED");
            mSelected = null;
            return true;

        case DragEvent.ACTION_DRAG_LOCATION:
            x = event.getX();
            y = event.getY();
            mRecyclerView.removeCallbacks(mScrollRunnable);
            mScrollRunnable.run();
            mRecyclerView.invalidate();
            return true;
    }
    return false;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)