在Android中的GridView中拖放

时间:2012-10-02 12:48:32

标签: android gridview drag-and-drop

如何在Android GridView中实现拖放功能。任何人都可以提供相同的最佳链接吗?

5 个答案:

答案 0 :(得分:6)

请参阅PagedDragDropGrid

上面的示例使用ViewGroup实现了一个带有拖放'可移动项目的分页网格。

注意@ 它支持Android 2.2(API 8)及更高版本。

答案 1 :(得分:3)

This是我在android拖放android 2.2中见过的最好的例子。您使用的是哪个版本?

答案 2 :(得分:1)

您可以在拖放here和第三方示例here上找到google的文档。

您要做的是将gridView中的每个视图设置为可单击并设置onTouchListener。在onTouch方法中,您将处理ACTION_DOWN(用户在屏幕上按下),ACTION_MOVE(用户在屏幕上移动手指)和ACTION_UP(用户从屏幕上抬起手指)的相应操作。

答案 3 :(得分:1)

使用WindowManager尝试另一种方法:

    package com.example.cooldraganddrop;

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Color;
    import android.graphics.PixelFormat;
    import android.graphics.drawable.BitmapDrawable;

    import android.util.AttributeSet;
    import android.view.Gravity;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.AdapterView;
    import android.widget.ImageView;

    public class CoolDragAndDropGridView extends SpanVariableGridView implements `View.OnTouchListener {`

        private static final int ITEM_HOVER_DELAY = 450;

        private int mDragPointX;
        private int mDragPointY;
        private int mDragOffsetX;
        private int mDragOffsetY;
        private int mDragPosition = AdapterView.INVALID_POSITION;
        private int mDropPosition = AdapterView.INVALID_POSITION;
        private int mCurrentPosition = AdapterView.INVALID_POSITION;
        private Runnable mDelayedOnDragRunnable = null;

        ScrollingStrategy mScrollingStrategy = null;
        WindowManager mWindowManager = null;
        WindowManager.LayoutParams mWindowParams = null;
        private ImageView mDragImageView = null;
        private boolean mDragAndDropStarted = false;
        private DragAndDropListener mDragAndDropListener = null;
        private OnTrackTouchEventsListener mOnTrackTouchEventsListener = null;

        public static interface OnTrackTouchEventsListener {

                void trackTouchEvents(final MotionEvent motionEvent);

        };

        public static interface DragAndDropListener {

                void onDragItem(int from);

                void onDraggingItem(int from, int to);

                void onDropItem(int from, int to);

                boolean isDragAndDropEnabled(int position);
        }

        public CoolDragAndDropGridView(Context context) {
                super(context);

                initialize();
        }

        public CoolDragAndDropGridView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);

                initialize();
        }

        public CoolDragAndDropGridView(Context context, AttributeSet attrs) {
                super(context, attrs);

                initialize();
        }

        private void initialize() {
                setOnTouchListener(this);
                setChildrenDrawingOrderEnabled(true);
        }

        public void startDragAndDrop() {

                mDragAndDropStarted = true;

        }

        public void setDragAndDropListener(DragAndDropListener dragAndDropListener) {

                mDragAndDropListener = dragAndDropListener;

        }

        private void destroyDragImageView() {

                if (mDragImageView != null) {

                        mWindowManager.removeView(mDragImageView);

                        BitmapDrawable bitmapDrawable = (BitmapDrawable) mDragImageView.getDrawable();
                        if (bitmapDrawable != null) {
                                final Bitmap bitmap = bitmapDrawable.getBitmap();
                                if (bitmap != null && !bitmap.isRecycled()) {
                                        bitmap.recycle();
                                }
                        }

                        mDragImageView.setImageDrawable(null);
                        mDragImageView = null;
                }

        }

        private ImageView createDragImageView(final View v, final int x, final int y) {

                v.destroyDrawingCache();
                v.setDrawingCacheEnabled(true);
                Bitmap bm = Bitmap.createBitmap(v.getDrawingCache());

                mDragPointX = x - v.getLeft();
                mDragPointY = y - v.getTop();

                mWindowParams = new WindowManager.LayoutParams();
                mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;

                mWindowParams.x = x - mDragPointX + mDragOffsetX;
                mWindowParams.y = y - mDragPointY + mDragOffsetY;

                mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
                mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
                mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

                mWindowParams.format = PixelFormat.TRANSLUCENT;
                mWindowParams.alpha = 0.7f;
                mWindowParams.windowAnimations = 0;

                ImageView iv = new ImageView(getContext());
                iv.setBackgroundColor(Color.parseColor("#ff555555"));
                iv.setImageBitmap(bm);

                mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
                mWindowManager.addView(iv, mWindowParams);
                return iv;

        }

        private void startDrag(final int x, final int y) {

                final View v = getChildAt(mDragPosition);

                destroyDragImageView();

                mDragImageView = createDragImageView(v, x, y);
                v.setVisibility(View.INVISIBLE);

                if (mDragAndDropListener != null) {

                        mDragAndDropListener.onDragItem(mDragPosition);
                }

        }

        @Override
        protected int getChildDrawingOrder(int childCount, int i) {
                if (mCurrentPosition == -1)
                        return i;
                else if (i == childCount - 1)
                        return mCurrentPosition;
                else if (i >= mCurrentPosition)
                        return i + 1;
                return i;
        }

        private void onDrop() {

                destroyDragImageView();

                removeCallbacks(mDelayedOnDragRunnable);

                View v = getChildAt(mDropPosition);
                v.setVisibility(View.VISIBLE);

                v.clearAnimation();

                if (mDragAndDropListener != null && mDropPosition != AdapterView.INVALID_POSITION) {

                        mDragAndDropListener.onDropItem(mDragPosition, mDropPosition);
                }

                mDragPosition = mDropPosition = mCurrentPosition = AdapterView.INVALID_POSITION;
                mDragAndDropStarted = false;
        }

        public void setScrollingStrategy(ScrollingStrategy scrollingStrategy) {

                mScrollingStrategy = scrollingStrategy;

        }

        private void onDrag(final int x, final int y) {

                if (mScrollingStrategy != null && mScrollingStrategy.performScrolling(x, y, this)) {

                        removeCallbacks(mDelayedOnDragRunnable);

                        return;
                }

                final int tempDropPosition = pointToPosition(mCurrentPosition, x, y);

                if (mDragAndDropListener != null && mDropPosition != tempDropPosition && tempDropPosition != AdapterView.INVALID_POSITION) {

                        removeCallbacks(mDelayedOnDragRunnable);

                        if (mDragAndDropListener.isDragAndDropEnabled(tempDropPosition)) {

                                mDropPosition = tempDropPosition;

                                mDelayedOnDragRunnable = new Runnable() {

                                        @Override
                                        public void run() {

                                                mDragAndDropListener.onDraggingItem(mCurrentPosition, tempDropPosition);
                                                performDragAndDropSwapping(mCurrentPosition, tempDropPosition);

                                                final int nextDropPosition = pointToPosition(tempDropPosition, x, y);

                                                if (nextDropPosition == AdapterView.INVALID_POSITION) {

                                                        mCurrentPosition = mDropPosition = tempDropPosition;

                                                }
                                        }
                                };

                                postDelayed(mDelayedOnDragRunnable, ITEM_HOVER_DELAY);

                        } else {

                                mDropPosition = mDragPosition;

                        }

                }

                if (mDragImageView != null) {

                        mWindowParams.x = x - mDragPointX + mDragOffsetX;
                        mWindowParams.y = y - mDragPointY + mDragOffsetY;
                        mWindowManager.updateViewLayout(mDragImageView, mWindowParams);
                }

        }

        public void setOnTrackTouchEventListener(OnTrackTouchEventsListener onTrackTouchEventsListener) {

                mOnTrackTouchEventsListener = onTrackTouchEventsListener;
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {

                if (mOnTrackTouchEventsListener != null) {
                        mOnTrackTouchEventsListener.trackTouchEvents(event);
                }

                switch (event.getAction()) {

                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:

                        if (mDragAndDropListener != null && mDragAndDropStarted) {

                                mDragAndDropStarted = false;

                                getParent().requestDisallowInterceptTouchEvent(true);

                                return launchDragAndDrop(event);
                        }

                        break;

                default:
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:

                        mDragAndDropStarted = false;

                        getParent().requestDisallowInterceptTouchEvent(false);

                        break;
                }

                return super.onInterceptTouchEvent(event);
        }

        private boolean launchDragAndDrop(final MotionEvent event) {

                final int x = (int) event.getX();
                final int y = (int) event.getY();

                mCurrentPosition = mDragPosition = mDropPosition = pointToPosition(mDragPosition, x, y);

                if (mDragPosition != AdapterView.INVALID_POSITION && mDragAndDropListener.isDragAndDropEnabled(mDragPosition)) {

                        mDragOffsetX = (int) (event.getRawX() - x);
                        mDragOffsetY = (int) (event.getRawY() - y);

                        startDrag(x, y);

                        return true;
                }

                return false;
        }

        @Override
        public boolean onTouch(View view, MotionEvent event) {

                if (mDragPosition != AdapterView.INVALID_POSITION && mDragImageView != null) {

                        final int x = (int) event.getX();
                        final int y = (int) event.getY();

                        switch (event.getAction()) {

                        case MotionEvent.ACTION_MOVE:

                                mDragOffsetX = (int) (event.getRawX() - x);
                                mDragOffsetY = (int) (event.getRawY() - y);

                                onDrag(x, y);

                                break;

                        case MotionEvent.ACTION_UP:
                        case MotionEvent.ACTION_CANCEL:

                                onDrop();

                                resetLongClickTransition();

                                getParent().requestDisallowInterceptTouchEvent(false);

                                return false;

                        default:

                        }

                        return true;
                }

                return false;
        }
}

使用这种拖放方法的示例是here

答案 4 :(得分:0)

最好的方法是扩展标准的Gridview控件,因为您可以将它与其他标准代码集成,例如用于适配器或数据结构的代码(也适用于Listviews等)。您可能需要识别需要拖动的项目,可能是长按,然后隐藏源视图,并绘制一个覆盖位图副本,当用户将手指放下时,该副本将在屏幕上移动。在修饰时,您会看到拖动源已被放置的位置,并且您要么将其移动到那里,要么删除其中一个(如果通过删除区域删除,就像在Android主屏幕gridview中一样)。 custom gridview with drag and drop example

作为了解更多细节的一个很好的链接,我会推荐一篇我最近写过的文章,解释所有内容并提供开源项目代码。链接是:http://www.pocketmagic.net/2013/11/complex-android-gridview-with-drag-and-drop-functionality/ 也可在Google代码上找到:http://code.google.com/p/android-gridview-drag-and-drop/

在youtube上演示视频: http://www.youtube.com/watch?v=m4yktX3SWSs

希望这有帮助!