将Listview项目拖放到另一个项目中

R4j*_*R4j 5 android drag-and-drop android-listview

我有一个列表视图与不同的项目类型:标题,文件夹和文件,如下所示:

在此输入图像描述

现在我想实现拖动文件项并将其放入文件夹项并获取源和目标位置.我不想像拖动排序列表视图库那样拖动时更改目标位置(重新排列).

有什么建议可以开始吗?

Lor*_*nMK 2

切换到ListView将使RecyclerView事情变得容易得多。

您可以在此处找到有关 Android 样式的整篇文章和完整代码

此代码用于OnItemTouchListener检测何时应拖动项目。ImageView上面有一个RecyclerView项目的图像被移动以便宜地动画它。

OnItemTouckListenerDragController.java):

public class DragController implements RecyclerView.OnItemTouchListener {
    private RecyclerView recyclerView;
    private ImageView overlay;
    private final GestureDetectorCompat gestureDetector;

    private boolean isDragging = false;

    public DragController(RecyclerView recyclerView, ImageView overlay) {
        this.recyclerView = recyclerView;
        this.overlay = overlay;
        GestureDetector.SimpleOnGestureListener longClickGestureListener = new GestureDetector.SimpleOnGestureListener() {
            @Override
            public void onLongPress(MotionEvent e) {
                super.onLongPress(e);
                isDragging = true;
                dragStart(e.getX(), e.getY());
            }
        };
        this.gestureDetector = new GestureDetectorCompat(recyclerView.getContext(), longClickGestureListener);
    }

    @Override
    public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
        if (isDragging) {
            return true;
        }
        gestureDetector.onTouchEvent(e);
        return false;
    }

    @Override
    public void onTouchEvent(RecyclerView rv, MotionEvent e) {
        int x = (int) e.getX();
        int y = (int) e.getY();
        View view = recyclerView.findChildViewUnder(x, y);
        if (e.getAction() == MotionEvent.ACTION_UP) {
            dragEnd(view);
            isDragging = false;
        } else {
            drag(y, view);
        }
    }
Run Code Online (Sandbox Code Playgroud)

开始和结束拖动 ( DragController.java):

private boolean isFirst = true;
private static final int ANIMATION_DURATION = 100;
private int draggingItem = -1;
private float startY = 0f;
private Rect startBounds = null;

private void dragStart(float x, float y) {
    View draggingView = recyclerView.findChildViewUnder(x, y);
    View first = recyclerView.getChildAt(0);
    isFirst = draggingView == first;
    startY = (y - draggingView.getTop());
    paintViewToOverlay(draggingView);
    overlay.setTranslationY(y - startY);
    draggingView.setVisibility(View.INVISIBLE);
    draggingItem = recyclerView.indexOfChild(draggingView);
    startBounds = new Rect(draggingView.getLeft(), draggingView.getTop(), draggingView.getRight(), draggingView.getBottom());
}

private void drag(int y, View view) {
    overlay.setTranslationY(y - startY);
}

private void dragEnd(View view) {
    overlay.setImageBitmap(null);
    view.setVisibility(View.VISIBLE);
    view.setTranslationY(overlay.getTranslationY() - view.getTop());
    view.animate().translationY(0f).setDuration(ANIMATION_DURATION).start();
}

private void paintViewToOverlay(View view) {
    Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    view.draw(canvas);
    overlay.setImageBitmap(bitmap);
    overlay.setTop(0);
}
Run Code Online (Sandbox Code Playgroud)

该代码由 Mark Allison 在 StylingAndroid 上编写

编辑:

但我不知道拖动结束时如何获取项目的位置

答案位于Android 样式第 7 部分。

View view = recyclerView.findChildViewUnder(0, y);
Run Code Online (Sandbox Code Playgroud)

如何禁用文件夹和标题项目上的拖动?只允许拖动文件项?

您可以通过使用多个 ViewType(文件、文件夹和标题)来完成此操作。然后您可以使用getItemViewTypeDragController仅启动文件的移动。