可拖拽ListView

原创 2017年05月05日 17:15:01

前期内容可参考

 1. WindowManager.LayoutParams详解总结和对应实例

 2. Android 自定义可拖拽ListView,思想最重要。


备忘代码如下:

public class DragListView extends ListView {

    private BaseAdapter mAdapter;
    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mWindowLayoutParams;
    private Vibrator mVibrator;
    private int mSelectedPosition;
    private Bitmap mDragBmp;
    ;
    private ImageView mDragImg;
    private boolean isDrag = false;
    private int mDownX;
    private int mDownY;
    private int mPoint2ItemTop;//按下的点到所在item的上边缘的距离
    private int mOffset2Top; //DragListView距离屏幕顶部的偏移量
    private int mDownScrollBorder;
    private int mUpScrollBorder;
    private int speed = 20;

    private View mSelectedItemView;
    private Handler mHandler = new Handler();
    private long mLongClickTime = 1000;
    private List<?> mListData;

    public DragListView(Context context) {
        super(context);
        init();
    }

    public DragListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DragListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * TODO 需要在调用完setAdapter后,接着调用这个,Adapter必须是BaseAdapter的子类
     *
     * @param data
     */
    public void setListData(List<?> data) {
        mListData = data;
        mAdapter = (BaseAdapter) getAdapter();
    }

    private void init() {
        mAdapter = (BaseAdapter) getAdapter();
        mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
        mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        //setOnItemLongClickListener();
    }

    private Runnable mLongClickRunnable = new Runnable() {
        @Override
        public void run() {
            isDrag = true;
            mVibrator.vibrate(100);
            createDragImage();
            if (mSelectedItemView != null) {
                mSelectedItemView.setVisibility(View.INVISIBLE);
            }
        }
    };


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = (int) event.getX();
                mDownY = (int) event.getY();
                mSelectedPosition = pointToPosition(mDownX, mDownY);
                if (mSelectedPosition == AdapterView.INVALID_POSITION) {
                    return super.onTouchEvent(event);
                }
                mSelectedItemView = getChildAt(mSelectedPosition - getFirstVisiblePosition());
                mHandler.postDelayed(mLongClickRunnable, mLongClickTime);

                mPoint2ItemTop = mDownY - mSelectedItemView.getTop();
                mOffset2Top = (int) (event.getRawY() - mDownY);

                mDownScrollBorder = getHeight() / 4;
                mUpScrollBorder = getHeight() * 3 / 4;
                break;
            case MotionEvent.ACTION_MOVE:
                if (isDrag) {
                    mDownX = (int) event.getX();
                    mDownY = (int) event.getY();
                    onDragStart();
                }
                break;
            case MotionEvent.ACTION_UP:
                onDragStop();
                mHandler.removeCallbacks(mLongClickRunnable);
                isDrag = false;
                break;
        }
        return super.onTouchEvent(event);
    }

    private void createDragImage() {
        mSelectedItemView.setDrawingCacheEnabled(true);
        mDragBmp = Bitmap.createBitmap(mSelectedItemView.getDrawingCache());
        mSelectedItemView.setDrawingCacheEnabled(false);
        mSelectedItemView.destroyDrawingCache();

        mWindowLayoutParams = new WindowManager.LayoutParams();
        mWindowLayoutParams.alpha = 0.5f;
        mWindowLayoutParams.format = PixelFormat.RGBA_8888;
        mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
        mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
        mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                | WindowManager.LayoutParams.FLAG_FULLSCREEN;
        mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
        mWindowLayoutParams.x = 0;
        mWindowLayoutParams.y = mDownY - mPoint2ItemTop + mOffset2Top;
        mDragImg = new ImageView(getContext());
        mDragImg.setImageBitmap(mDragBmp);
        mWindowManager.addView(mDragImg, mWindowLayoutParams);
    }


    private void onDragStart() {
        if (mWindowLayoutParams != null && mDragImg != null) {
            mWindowLayoutParams.x = 0;
            mWindowLayoutParams.y = mDownY - mPoint2ItemTop + mOffset2Top;
            mWindowManager.updateViewLayout(mDragImg, mWindowLayoutParams);
        }
        int scrollY;
        if (mDownY > mUpScrollBorder) {
            scrollY = speed;
        } else if (mDownY < mDownScrollBorder) {
            scrollY = -speed;
        } else {
            scrollY = 0;
        }
        smoothScrollBy(scrollY, 0);

        int position = pointToPosition(mDownX, mDownY);
        if (position != mSelectedPosition && position != AdapterView.INVALID_POSITION) {
            if (mListData != null) {
                if (mSelectedPosition < position) {
                    for (int i = mSelectedPosition; i < position; i++) {
                        Collections.swap(mListData, i, i + 1);
                    }
                } else if (mSelectedPosition > position) {
                    for (int i = mSelectedPosition; i > position; i--) {
                        Collections.swap(mListData, i, i - 1);
                    }
                }
                mAdapter.notifyDataSetChanged();
            }
            View view1 = getChildAt(mSelectedPosition - getFirstVisiblePosition());
            if (view1 != null) {
                view1.setVisibility(View.VISIBLE);
            }
            View view2 = getChildAt(position - getFirstVisiblePosition());
            if (view2 != null) {
                view2.setVisibility(View.INVISIBLE);
            }
            mSelectedPosition = position;
        }
    }

    private void onDragStop() {
        View view = getChildAt(mSelectedPosition - getFirstVisiblePosition());
        if (view != null) {
            view.setVisibility(View.VISIBLE);
        }

        if (mWindowLayoutParams != null && mDragImg != null) {
            mWindowManager.removeView(mDragImg);
            mDragImg = null;
            mDragBmp.recycle();
            mDragBmp = null;
        }
    }
}










Android 自定义可拖拽ListView,思想最重要。

最近好多小伙伴都结婚了,甚至还有二婚的,我终于总结出为什么如此热爱生活的同时,钱包却一直不见涨的原因。想想以后的日子,结婚的生孩子,二婚的生孩子,然后有的结婚,有的二婚,有的多婚。。深深感叹:时不我待...
  • gaoshouxiaodi
  • gaoshouxiaodi
  • 2015年05月07日 09:47
  • 4455

自定义控件——可拖拽排序的ListView

前言最经研究了一下拖拽排序的ListView,跟酷狗里的播放列表排序一样,但因为要添加自己特有的功能,所以研究了好长时间。一开始接触的是GitHub的开源项目——DragSortListView,实现...
  • a10615
  • a10615
  • 2016年05月12日 01:44
  • 12038

Android自定义View——可拖拽的ListView

有时时候需要对ListView的Item进行手动拖拽排序,如安桌系统中的对通知栏的开关排序,因此需要自定义一个可拖拽的ListView,效果如下: 可见,该ListView只有已添加栏可以拖动,且...
  • u012964944
  • u012964944
  • 2016年08月03日 15:27
  • 2028

实现可拖动排序的ListView-DragListView

项目 中要用到拖动排序的效果,于是百度到网上的做法,github上开源框架被我pass, 为了一个小功能导入一库太不划算。然后看到这遍 http://blog.csdn.net/jj120522/ar...
  • u012325403
  • u012325403
  • 2015年12月24日 13:50
  • 718

推荐一个可以拖动和侧滑Item的ListView开源组件

https://github.com/yydcdut/SlideAndDragListViewSlideAndDragListView     A ListView that you can slid...
  • zhangcanyan
  • zhangcanyan
  • 2017年04月05日 20:35
  • 552

ListView之间的拖放功能的实现

ListView之间的拖放功能的实现主要是要实现三个事件:ItemDrag,DragEnter,DragDrop.这三个事件只有第一个事件是当前listview触发的。其它的两个都是由目标listvi...
  • webajax
  • webajax
  • 2008年01月29日 16:02
  • 2773

android listview拖拽,拖动item 改变位置

转自:http://blog.csdn.net/dany1202/article/details/6109160#comments 在packages/apps/Music/src/...
  • lianghongge
  • lianghongge
  • 2013年11月09日 19:50
  • 1985

ListView拖拽交换 item 的实现(QQ 分组管理功能)

在写这篇文章前,碰巧看到有个哥们也做了这个功能,【Android】可拖拽排序的ListView。而且就在几个小时前发表的,本来想还是算了,我就不写这个功能,不过我大致浏览了他的实现原理跟我的实现原理还...
  • jxxfzgy
  • jxxfzgy
  • 2015年03月18日 23:17
  • 2421

一个可拖动的ScrollView

我们经常看到这样的效果,一个ListView和GridView亦或者是RecycleView,再上拉或下拉到顶部的时候,还能再拖拽一段距离,这种效果是是非常常见的,因为用的比较多,所以记录一下. ...
  • fenganit
  • fenganit
  • 2016年12月19日 09:29
  • 669

listview长按后拖动item交换位置的帮助类

抽象类封装,需要在activity中创建帮助类对象并重写交换位置的方法changeItemPosition(数据源中id1,数据源中的id2),和重新显示listview的方法resetListvie...
  • u014727233
  • u014727233
  • 2016年05月10日 13:29
  • 2145
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:可拖拽ListView
举报原因:
原因补充:

(最多只允许输入30个字)