draggable可拖动的ListView,并且支持行删除功能

时间:2022-02-13 19:45:59
看图,拖动前:
draggable可拖动的ListView,并且支持行删除功能
拖动后:
draggable可拖动的ListView,并且支持行删除功能

package com.ql.view;

import com.ql.activity.R;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;

/**
 * draggable可拖动的列表,并且支持行删除功能
 * @author admin
 *
 */
public class DraggableListView extends ListView {

	private DropListener mDropListener;

	private ImageView mDragView;
	private int mDragPos; // which item is being dragged
	private int mFirstDragPos; // where was the dragged item originally
	private int mDragPoint; // at what offset inside the item did the user grab
							// it
	private int mCoordOffset; // the difference between screen coordinates and
								// coordinates in this view

	private Rect mTempRect = new Rect();
	private final int mTouchSlop;
	private int mHeight;
	private int mUpperBound;
	private int mLowerBound;
	private WindowManager mWindowManager;
	private WindowManager.LayoutParams mWindowParams;
	private int dragndropBackgroundColor = 0x00000000;
	private Bitmap mDragBitmap;
	private int mItemHeightHalf = 32;
	private int mItemHeightNormal = 64;
	private int mItemHeightExpanded = 128;
	//private int grabberId=-1;

	public DraggableListView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
		// TODO Auto-generated constructor stub
	}

	public DraggableListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		// TODO Auto-generated constructor stub
		mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
		
//		if (attrs!=null) {
//			TypedArray a=getContext().obtainStyledAttributes(attrs,R.styleable.TouchListView,0, 0);
//
//			mItemHeightNormal=a.getDimensionPixelSize(R.styleable.TouchListView_normal_height, 0);
//			mItemHeightExpanded=a.getDimensionPixelSize(R.styleable.TouchListView_expanded_height, mItemHeightNormal);
//			grabberId=a.getResourceId(R.styleable.TouchListView_grabber, -1);
//			dragndropBackgroundColor=a.getColor(R.styleable.TouchListView_dragndrop_background, 0x00000000);
//			//mRemoveMode=a.getInt(R.styleable.TouchListView_remove_mode, -1);
//
//			a.recycle();
//		}

	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
//		Log.v(">>>>>>>>>>onTouchEvent", ">>>>>>>>>>onTouchEvent");
		if ((mDropListener != null) && mDragView != null) {
			int action = ev.getAction();
			switch (action) {
			case MotionEvent.ACTION_UP:
			case MotionEvent.ACTION_CANCEL:
				Rect r = mTempRect;
				mDragView.getDrawingRect(r);
				stopDragging();
				if (mDropListener != null && mDragPos >= 0
						&& mDragPos < getCount()) {
					mDropListener.drop(mFirstDragPos, mDragPos);
				}
				unExpandViews(false);
				break;

			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_MOVE:
				int x = (int) ev.getX();
				int y = (int) ev.getY();
				dragView(x, y);

				int itemnum = getItemForPosition(y);
				if (itemnum >= 0) {
					if (action == MotionEvent.ACTION_DOWN
							|| itemnum != mDragPos) {

						mDragPos = itemnum;
						doExpansion();
//						Log.v(">>>doExpansion", ">>>>>>>>>>doExpansion");
					}
					/*
					int speed = 0;
					adjustScrollBounds(y);
					if (y > mLowerBound) {
						// scroll the list up a bit
						speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;
					} else if (y < mUpperBound) {
						// scroll the list down a bit
						speed = y < mUpperBound / 2 ? -16 : -4;
					}
					if (speed != 0) {
						int ref = pointToPosition(0, mHeight / 2);
						if (ref == AdapterView.INVALID_POSITION) {
							// we hit a divider or an invisible view, check
							// somewhere else
							ref = pointToPosition(0, mHeight / 2
									+ getDividerHeight() + 64);
						}
						View v = getChildAt(ref - getFirstVisiblePosition());
						if (v != null) {
							int pos = v.getTop();
							setSelectionFromTop(ref, pos - speed);

						}
					}
					*/
				}
				break;
			}
			return true;
		}
		return super.onTouchEvent(ev);

	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		if (mDropListener != null) {
			switch (ev.getAction()) {
			case MotionEvent.ACTION_DOWN:
				int x = (int) ev.getX();
				int y = (int) ev.getY();
				int itemnum = pointToPosition(x, y);
//				Log.v("itemnum>>>", ">>>>>>>>" + itemnum);
				if (itemnum == AdapterView.INVALID_POSITION) {
					break;
				}
				ViewGroup item = (ViewGroup) getChildAt(itemnum
						- getFirstVisiblePosition());
//				Log.v("itemnum>>>", ">>>>>>>>" + getFirstVisiblePosition()
//						+ "---" + ev.getRawY() + "----" + ev.getY()+"-----"+item.getTop());
				mDragPoint = y - item.getTop();
				mCoordOffset = ((int) ev.getRawY()) - y;
				View dragger = item.findViewById(R.id.iconimg);//拖动的ImageView
				Rect r = mTempRect;
				// dragger.getDrawingRect(r);

				r.left = dragger.getLeft();
				r.right = dragger.getRight();
				r.top = dragger.getTop();
				r.bottom = dragger.getBottom();

				if ((r.left < x) && (x < r.right)) {
					item.setDrawingCacheEnabled(true);
					// Create a copy of the drawing cache so that it does not
					// get recycled
					// by the framework when the list tries to clean up memory
					Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());
					startDragging(bitmap, y);
					mDragPos = itemnum;
					mFirstDragPos = mDragPos;
					mHeight = getHeight();
					int touchSlop = mTouchSlop;
					mUpperBound = Math.min(y - touchSlop, mHeight / 3);
					mLowerBound = Math.max(y + touchSlop, mHeight * 2 / 3);
					return false;
				}
				//
				View delView = item.findViewById(R.id.delete);//删除的ImageView
				r.left = delView.getLeft();
				r.right = delView.getRight();
				r.top = delView.getTop();
				r.bottom = delView.getBottom();
				if ((r.left < x) && (x < r.right)) {
					mDropListener.onDeleteClicked(itemnum);
					return false;
				}

				mDragView = null;
				break;
			}
		}
		return super.onInterceptTouchEvent(ev);
	}

	private void startDragging(Bitmap bm, int y) {
		stopDragging();

		mWindowParams = new WindowManager.LayoutParams();
		mWindowParams.gravity = Gravity.TOP;
		mWindowParams.x = 0;
		mWindowParams.y = y - mDragPoint + mCoordOffset;

		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.windowAnimations = 0;

		ImageView v = new ImageView(getContext());
		// int backGroundColor =
		// getContext().getResources().getColor(R.color.dragndrop_background);
		v.setBackgroundColor(dragndropBackgroundColor);
		v.setImageBitmap(bm);
		mDragBitmap = bm;

		mWindowManager = (WindowManager) getContext()
				.getSystemService("window");
		mWindowManager.addView(v, mWindowParams);
		mDragView = v;
	}

	private void stopDragging() {
		if (mDragView != null) {
			WindowManager wm = (WindowManager) getContext().getSystemService(
					"window");
			wm.removeView(mDragView);
			mDragView.setImageDrawable(null);
			mDragView = null;
		}
		if (mDragBitmap != null) {
			mDragBitmap.recycle();
			mDragBitmap = null;
		}
	}

	private void dragView(int x, int y) {
		float alpha = 1.0f;
		mWindowParams.alpha = alpha;
		// }
		mWindowParams.y = y - mDragPoint + mCoordOffset;
		mWindowManager.updateViewLayout(mDragView, mWindowParams);
	}

	private int getItemForPosition(int y) {
		int adjustedy = y - mDragPoint - mItemHeightHalf;
		int pos = myPointToPosition(0, adjustedy);
		if (pos >= 0) {
			if (pos <= mFirstDragPos) {
				pos += 1;
			}
		} else if (adjustedy < 0) {
			pos = 0;
		}
		return pos;
	}

	private void adjustScrollBounds(int y) {
		if (y >= mHeight / 3) {
			mUpperBound = mHeight / 3;
		}
		if (y <= mHeight * 2 / 3) {
			mLowerBound = mHeight * 2 / 3;
		}
	}

	/*
	 * Restore size and visibility for all listitems
	 */
	private void unExpandViews(boolean deletion) {
		for (int i = 0;; i++) {
			View v = getChildAt(i);
			if (v == null) {
				if (deletion) {
					// HACK force update of mItemCount
					int position = getFirstVisiblePosition();
					int y = getChildAt(0).getTop();
					setAdapter(getAdapter());
					setSelectionFromTop(position, y);
					// end hack
				}
				layoutChildren(); // force children to be recreated where needed
				v = getChildAt(i);
				if (v == null) {
					break;
				}
			}
			ViewGroup.LayoutParams params = v.getLayoutParams();
			params.height = mItemHeightNormal;
			v.setLayoutParams(params);
			v.setVisibility(View.VISIBLE);
		}
	}

	/*
	 * Adjust visibility and size to make it appear as though an item is being
	 * dragged around and other items are making room for it: If dropping the
	 * item would result in it still being in the same place, then make the
	 * dragged listitem's size normal, but make the item invisible. Otherwise,
	 * if the dragged listitem is still on screen, make it as small as possible
	 * and expand the item below the insert point. If the dragged item is not on
	 * screen, only expand the item below the current insertpoint.
	 */
	private void doExpansion() {
		int childnum = mDragPos - getFirstVisiblePosition();
		if (mDragPos > mFirstDragPos) {
			childnum++;
		}

		View first = getChildAt(mFirstDragPos - getFirstVisiblePosition());

		for (int i = 0;; i++) {
			View vv = getChildAt(i);
			if (vv == null) {
				break;
			}
			int height = mItemHeightNormal;
			int visibility = View.VISIBLE;
			if (vv.equals(first)) {
				// processing the item that is being dragged
				if (mDragPos == mFirstDragPos) {
					// hovering over the original location
					visibility = View.INVISIBLE;
				} else {
					// not hovering over it
					height = 1;
				}
			} else if (i == childnum) {
				if (mDragPos < getCount() - 1) {
					height = mItemHeightExpanded;
				}
			}
			ViewGroup.LayoutParams params = vv.getLayoutParams();
			params.height = height;
			vv.setLayoutParams(params);
			vv.setVisibility(visibility);
		}
	}

	/*
	 * pointToPosition() doesn't consider invisible views, but we need to, so
	 * implement a slightly different version.
	 */
	private int myPointToPosition(int x, int y) {
		Rect frame = mTempRect;
		final int count = getChildCount();
		for (int i = count - 1; i >= 0; i--) {
			final View child = getChildAt(i);
			child.getHitRect(frame);
			if (frame.contains(x, y)) {
				return getFirstVisiblePosition() + i;
			}
		}
		return INVALID_POSITION;
	}

	public interface DropListener {
		//
		void drop(int from, int to);
		//
		void onDeleteClicked(int index);
	}

	public void setDropListener(DropListener onDrop) {
		// TODO Auto-generated method stub
		mDropListener = onDrop;
	}

}


使用:
package com.ql.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;


import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

import com.ql.view.DraggableListView;


public class Test_6_Activity  extends Activity{
	private DraggableListView	mListView;
	private DraggableArrayAdapter adapter = null;
	private ArrayList<Map<String, String>> array;
//	private	int	mIndex;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.test5);
		
		mListView = (DraggableListView) findViewById(R.id.draggable_list);  
		array = getData();
		adapter = new DraggableArrayAdapter();
		mListView.setAdapter(adapter);
		
		mListView.setDropListener(onDrop);
//		mListView.getAdapter();
//		//列表点击事件处理
//        mListView.setOnItemClickListener(new OnItemClickListener() {
//
//        	@Override
//        	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
//        							long arg3) {
//        		
//        		//Toast.makeText(context, "Click "+arg2, Toast.LENGTH_SHORT).show();
//        	}
//        });   
//        
//        mListView.setOnItemLongClickListener(new OnItemLongClickListener() {
//        	
//        	@Override
//        	public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position,
//        			long id) {
//        		mIndex = position;
//        		return false;
//        	}
//        });
	
	}
	//初始化数据
	private ArrayList<Map<String, String>> getData() {
		ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
		for(int i=0; i<5; i++) {
			Map<String, String> map = new HashMap<String, String>();
			map.put("code", "code"+i);
			map.put("name", "name"+i);
			list.add(map);
		}
		return list;
	}

	private DraggableListView.DropListener onDrop = new DraggableListView.DropListener() {
		@Override
		public void drop(int from, int to) {
			Map<String, String> item = adapter.getItem(from);
			adapter.remove(item);
			adapter.insert(item, to);
		}

		@Override
		public void onDeleteClicked(int index) {
//			mIndex = index;
			delete(index);
		}
	};
	private void delete(final int index) {
		String prompt = "delete "+array.get(index).get("name").toString()+" "+array.get(index).get("code").toString()+"?";
		//删除确认对话		
		new AlertDialog.Builder(Test_6_Activity.this)
			.setTitle("删除?")
			//.setIcon(android.R.drawable.ic_menu_help)
			.setMessage(prompt)
			.setCancelable(true)
			.setPositiveButton("确定", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					Map<String, String> item = adapter.getItem(index);
					adapter.remove(item);
				}
			})
			.setNegativeButton("取消", new DialogInterface.OnClickListener() {
				
				@Override
				public void onClick(DialogInterface dialog, int which) {
					dialog.cancel();
				}
			}).show();

	}
	/**
	 * 适配器
	 * @author admin
	 *
	 */
	class DraggableArrayAdapter extends ArrayAdapter<Map<String, String>> {

		DraggableArrayAdapter() {
			
			super(Test_6_Activity.this, R.layout.row_simple_list_item_4, array);
		}

		public ArrayList<Map<String, String>> getList() {
			return array;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			
			View row = convertView;
			if (row == null) {
				LayoutInflater inflater = getLayoutInflater();
				row = inflater.inflate(R.layout.row_simple_list_item_4, parent, false);
			}
			TextView code = (TextView) row.findViewById(R.id.code);
			code.setText(array.get(position).get("code").toString());
			TextView name = (TextView) row.findViewById(R.id.name);
			name.setText(array.get(position).get("name").toString());

			return (row);
		}
	}
}


text5.xml布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
  	android:orientation="vertical"
  	android:layout_width="fill_parent"
  	android:layout_height="fill_parent">

	<com.ql.view.DraggableListView
		android:id="@+id/draggable_list"
		android:layout_width="fill_parent" 
		android:layout_height="fill_parent"
		/>
</LinearLayout>

适配器中使用的布局文件row_simple_list_item_4.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    >
    <!-- 
    android:background="@drawable/list_bg"
     -->
    <ImageView android:id="@+id/iconimg"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
		android:src="@drawable/grabber"
		/>
		
    <ImageView android:id="@+id/delete"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    	android:paddingRight="5dip"
        android:src="@android:drawable/ic_delete"
		/>
		
	<TextView android:id="@+id/code"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="10dip"
        android:layout_toRightOf="@id/iconimg"
		android:layout_centerVertical="true"
		android:textSize="20dip"
		android:textColor="#888888"
		/>
	<TextView android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="10dip"
        android:layout_toRightOf="@id/code"
		android:layout_centerVertical="true"
		android:textSize="20dip"
		android:textColor="#888888"
		/>
		
</RelativeLayout>



另一个ListView:
http://blog.csdn.net/sodino/archive/2010/12/15/6077017.aspx
1.实现根据字母进行分类。
2.实现快速滑动。
3.实现快速滑动的提示。
4.实现快捷弹窗。

自定义Android ListView控件:ExpandableListView
http://www.pin5i.com/showtopic-custom-android-listview-control-expandablelistview.html

另一篇关于listview的拖动效果
android listview拖拽,拖动item 改变位置
http://blog.csdn.net/dany1202/archive/2010/12/31/6109160.aspx
在packages/apps/Music/src/touchIncepter.java中
该类提供了listview的拖动效果,并提供接口,在程序接口中实现数据的交换即可。
package com.and.DragListview;  
import java.util.ArrayList;  
import java.util.List;  
import android.app.ListActivity;  
import android.content.Context;  
import android.os.Bundle;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.view.ViewGroup;  
import android.widget.BaseAdapter;  
import android.widget.ImageView;  
import android.widget.TextView;  
public class DragListview extends ListActivity {     
    MyAdapter adapter;  
    TouchInterceptor list;  
    List<String> arrayText;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        list = (TouchInterceptor) getListView();//(TouchInterceptor)findViewById(android.R.id.list);  
        getText();  
          
        adapter = new MyAdapter(this);  
        setListAdapter(adapter);  
         
        list.setDropListener(mDropListener);  
     //   list.setRemoveListener(mRemoveListener);        
    }  
    public void getText(){  
        arrayText = new ArrayList<String>();  
        arrayText.add("传奇");  
        arrayText.add("红豆");  
        arrayText.add("流年");  
        arrayText.add("棋子");  
    }  
      
    //交换listview的数据  
    private TouchInterceptor.DropListener mDropListener =  
        new TouchInterceptor.DropListener() {  
        public void drop(int from, int to) {  
            String item = arrayText.get(from);  
            arrayText.remove(item);//.remove(from);  
            arrayText.add(to, item);  
            adapter.notifyDataSetChanged();  
        }  
    };  
      
    private TouchInterceptor.RemoveListener mRemoveListener =  
        new TouchInterceptor.RemoveListener() {  
        public void remove(int which) {            
        }  
    };  
      
    class MyAdapter extends BaseAdapter{  
        private LayoutInflater mInflater;  
        Context mContext;  
        public MyAdapter(Context c){  
            mInflater = LayoutInflater.from(c);  
        }  
        public int getCount() {           
            return arrayText.size();  
        }  
        public Object getItem(int arg0) {  
            return arrayText.get(arg0);  
        }  
        public long getItemId(int arg0) {  
            return arg0;  
        }  
        public View getView(int arg0, View contentView, ViewGroup arg2) {  
            ImageView img;  
            TextView text;  
            if(contentView==null){  
                contentView = mInflater.inflate(R.layout.list_layout, null);   
                //contentView = mInflater.inflate(R.layout.list_layout,null);  
            }  
            img = (ImageView)contentView.findViewById(R.id.img);  
            img.setBackgroundResource(R.drawable.icon);  
            text = (TextView)contentView.findViewById(R.id.text);  
            text.setText(arrayText.get(arg0).toString());  
              
            return contentView;  
        }  
          
    }  
}  

/* 
 * Copyright (C) 2008 The Android Open Source Project 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */  
package com.and.DragListview;  
import android.content.Context;  
import android.content.SharedPreferences;  
import android.content.res.Resources;  
import android.graphics.Bitmap;  
import android.graphics.PixelFormat;  
import android.graphics.Rect;  
import android.util.AttributeSet;  
import android.view.GestureDetector;  
import android.view.Gravity;  
import android.view.MotionEvent;  
import android.view.View;  
import android.view.ViewConfiguration;  
import android.view.ViewGroup;  
import android.view.WindowManager;  
import android.view.GestureDetector.SimpleOnGestureListener;  
import android.widget.AdapterView;  
import android.widget.ImageView;  
import android.widget.ListView;  
public class TouchInterceptor extends ListView {  
      
    private ImageView mDragView;  
    private WindowManager mWindowManager;  
    private WindowManager.LayoutParams mWindowParams;  
    private int mDragPos;      // which item is being dragged  
    private int mFirstDragPos; // where was the dragged item originally  
    private int mDragPoint;    // at what offset inside the item did the user grab it  
    private int mCoordOffset;  // the difference between screen coordinates and coordinates in this view  
    private DragListener mDragListener;  
    private DropListener mDropListener;  
    private RemoveListener mRemoveListener;  
    private int mUpperBound;  
    private int mLowerBound;  
    private int mHeight;  
    private GestureDetector mGestureDetector;  
    private static final int FLING = 0;  
    private static final int SLIDE = 1;  
    private int mRemoveMode = -1;  
    private Rect mTempRect = new Rect();  
    private Bitmap mDragBitmap;  
    private final int mTouchSlop;  
    private int mItemHeightNormal;  
    private int mItemHeightExpanded;  
    private int mItemHeightHalf;  
    public TouchInterceptor(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        SharedPreferences pref = context.getSharedPreferences("Music", 3);  
        mRemoveMode = pref.getInt("deletemode", -1);  
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
        Resources res = getResources();  
        mItemHeightNormal = 48;//res.getDimensionPixelSize(R.dimen.normal_height);  
        mItemHeightHalf = mItemHeightNormal / 2;  
        mItemHeightExpanded = 48;//res.getDimensionPixelSize(R.dimen.expanded_height);  
    }  
      
    @Override  
    public boolean onInterceptTouchEvent(MotionEvent ev) {  
        if (mRemoveListener != null && mGestureDetector == null) {  
            if (mRemoveMode == FLING) {  
                mGestureDetector = new GestureDetector(getContext(), new SimpleOnGestureListener() {  
                    @Override  
                    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,  
                            float velocityY) {  
                        if (mDragView != null) {  
                            if (velocityX > 1000) {  
                                Rect r = mTempRect;  
                                mDragView.getDrawingRect(r);  
                                if ( e2.getX() > r.right * 2 / 3) {  
                                    // fast fling right with release near the right edge of the screen  
                                    stopDragging();  
                                    mRemoveListener.remove(mFirstDragPos);  
                                    unExpandViews(true);  
                                }  
                            }  
                            // flinging while dragging should have no effect  
                            return true;  
                        }  
                        return false;  
                    }  
                });  
            }  
        }  
        if (mDragListener != null || mDropListener != null) {  
            switch (ev.getAction()) {  
                case MotionEvent.ACTION_DOWN:  
                    int x = (int) ev.getX();  
                    int y = (int) ev.getY();  
                    int itemnum = pointToPosition(x, y);  
                    if (itemnum == AdapterView.INVALID_POSITION) {  
                        break;  
                    }  
                    ViewGroup item = (ViewGroup) getChildAt(itemnum - getFirstVisiblePosition());  
                    mDragPoint = y - item.getTop();  
                    mCoordOffset = ((int)ev.getRawY()) - y;  
                    View dragger = item.findViewById(R.id.img);//..........................  
                    Rect r = mTempRect;  
                    dragger.getDrawingRect(r);  
                    // The dragger icon itself is quite small, so pretend the touch area is bigger  
                    if (x < r.right * 2) {  
                        item.setDrawingCacheEnabled(true);  
                        // Create a copy of the drawing cache so that it does not get recycled  
                        // by the framework when the list tries to clean up memory  
                        Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());  
                        startDragging(bitmap, y);  
                        mDragPos = itemnum;  
                        mFirstDragPos = mDragPos;  
                        mHeight = getHeight();  
                        int touchSlop = mTouchSlop;  
                        mUpperBound = Math.min(y - touchSlop, mHeight / 3);  
                        mLowerBound = Math.max(y + touchSlop, mHeight * 2 /3);  
                        return false;  
                    }  
                    stopDragging();  
                    break;  
            }  
        }  
        return super.onInterceptTouchEvent(ev);  
    }  
      
    /* 
     * pointToPosition() doesn't consider invisible views, but we 
     * need to, so implement a slightly different version. 
     */  
    private int myPointToPosition(int x, int y) {  
        if (y < 0) {  
            // when dragging off the top of the screen, calculate position  
            // by going back from a visible item  
            int pos = myPointToPosition(x, y + mItemHeightNormal);  
            if (pos > 0) {  
                return pos - 1;  
            }  
        }  
        Rect frame = mTempRect;  
        final int count = getChildCount();  
        for (int i = count - 1; i >= 0; i--) {  
            final View child = getChildAt(i);  
            child.getHitRect(frame);  
            if (frame.contains(x, y)) {  
                return getFirstVisiblePosition() + i;  
            }  
        }  
        return INVALID_POSITION;  
    }  
      
    private int getItemForPosition(int y) {  
        int adjustedy = y - mDragPoint - mItemHeightHalf;  
        int pos = myPointToPosition(0, adjustedy);  
        if (pos >= 0) {  
            if (pos <= mFirstDragPos) {  
                pos += 1;  
            }  
        } else if (adjustedy < 0) {  
            // this shouldn't happen anymore now that myPointToPosition deals  
            // with this situation  
            pos = 0;  
        }  
        return pos;  
    }  
      
    private void adjustScrollBounds(int y) {  
        if (y >= mHeight / 3) {  
            mUpperBound = mHeight / 3;  
        }  
        if (y <= mHeight * 2 / 3) {  
            mLowerBound = mHeight * 2 / 3;  
        }  
    }  
    /* 
     * Restore size and visibility for all listitems 
     */  
    private void unExpandViews(boolean deletion) {  
        for (int i = 0;; i++) {  
            View v = getChildAt(i);  
            if (v == null) {  
                if (deletion) {  
                    // HACK force update of mItemCount  
                    int position = getFirstVisiblePosition();  
                    int y = getChildAt(0).getTop();  
                    setAdapter(getAdapter());  
                    setSelectionFromTop(position, y);  
                    // end hack  
                }  
                layoutChildren(); // force children to be recreated where needed  
                v = getChildAt(i);  
                if (v == null) {  
                    break;  
                }  
            }  
            ViewGroup.LayoutParams params = v.getLayoutParams();  
            params.height = mItemHeightNormal;  
            v.setLayoutParams(params);  
            v.setVisibility(View.VISIBLE);  
        }  
    }  
      
    /* Adjust visibility and size to make it appear as though 
     * an item is being dragged around and other items are making 
     * room for it: 
     * If dropping the item would result in it still being in the 
     * same place, then make the dragged listitem's size normal, 
     * but make the item invisible. 
     * Otherwise, if the dragged listitem is still on screen, make 
     * it as small as possible and expand the item below the insert 
     * point. 
     * If the dragged item is not on screen, only expand the item 
     * below the current insertpoint. 
     */  
    private void doExpansion() {  
        int childnum = mDragPos - getFirstVisiblePosition();  
        if (mDragPos > mFirstDragPos) {  
            childnum++;  
        }  
        View first = getChildAt(mFirstDragPos - getFirstVisiblePosition());  
        for (int i = 0;; i++) {  
            View vv = getChildAt(i);  
            if (vv == null) {  
                break;  
            }  
            int height = mItemHeightNormal;  
            int visibility = View.VISIBLE;  
            if (vv.equals(first)) {  
                // processing the item that is being dragged  
                if (mDragPos == mFirstDragPos) {  
                    // hovering over the original location  
                    visibility = View.INVISIBLE;  
                } else {  
                    // not hovering over it  
                    height = 1;  
                }  
            } else if (i == childnum) {  
                if (mDragPos < getCount() - 1) {  
                    height = mItemHeightExpanded;  
                }  
            }  
            ViewGroup.LayoutParams params = vv.getLayoutParams();  
            params.height = height;  
            vv.setLayoutParams(params);  
            vv.setVisibility(visibility);  
        }  
    }  
      
    @Override  
    public boolean onTouchEvent(MotionEvent ev) {  
        if (mGestureDetector != null) {  
            mGestureDetector.onTouchEvent(ev);  
        }  
        if ((mDragListener != null || mDropListener != null) && mDragView != null) {  
            int action = ev.getAction();   
            switch (action) {  
                case MotionEvent.ACTION_UP:  
                case MotionEvent.ACTION_CANCEL:  
                    Rect r = mTempRect;  
                    mDragView.getDrawingRect(r);  
                    stopDragging();  
                    if (mRemoveMode == SLIDE && ev.getX() > r.right * 3 / 4) {  
                        if (mRemoveListener != null) {  
                            mRemoveListener.remove(mFirstDragPos);  
                        }  
                        unExpandViews(true);  
                    } else {  
                        if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount()) {  
                            mDropListener.drop(mFirstDragPos, mDragPos);  
                        }  
                        unExpandViews(false);  
                    }  
                    break;  
                      
                case MotionEvent.ACTION_DOWN:  
                case MotionEvent.ACTION_MOVE:  
                    int x = (int) ev.getX();  
                    int y = (int) ev.getY();  
                    dragView(x, y);  
                    int itemnum = getItemForPosition(y);  
                    if (itemnum >= 0) {  
                        if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {  
                            if (mDragListener != null) {  
                                mDragListener.drag(mDragPos, itemnum);  
                            }  
                            mDragPos = itemnum;  
                            doExpansion();  
                        }  
                        int speed = 0;  
                        adjustScrollBounds(y);  
                        if (y > mLowerBound) {  
                            // scroll the list up a bit  
                            speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;  
                        } else if (y < mUpperBound) {  
                            // scroll the list down a bit  
                            speed = y < mUpperBound / 2 ? -16 : -4;  
                        }  
                        if (speed != 0) {  
                            int ref = pointToPosition(0, mHeight / 2);  
                            if (ref == AdapterView.INVALID_POSITION) {  
                                //we hit a divider or an invisible view, check somewhere else  
                                ref = pointToPosition(0, mHeight / 2 + getDividerHeight() + 64);  
                            }  
                            View v = getChildAt(ref - getFirstVisiblePosition());  
                            if (v!= null) {  
                                int pos = v.getTop();  
                                setSelectionFromTop(ref, pos - speed);  
                            }  
                        }  
                    }  
                    break;  
            }  
            return true;  
        }  
        return super.onTouchEvent(ev);  
    }  
      
    private void startDragging(Bitmap bm, int y) {  
        stopDragging();  
        mWindowParams = new WindowManager.LayoutParams();  
        mWindowParams.gravity = Gravity.TOP;  
        mWindowParams.x = 0;  
        mWindowParams.y = y - mDragPoint + mCoordOffset;  
        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  
                | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;  
        mWindowParams.format = PixelFormat.TRANSLUCENT;  
        mWindowParams.windowAnimations = 0;  
          
        Context context = getContext();  
        ImageView v = new ImageView(context);  
//        int backGroundColor = context.getResources().getColor(R.color.dragndrop_background);  
//        v.setBackgroundColor(backGroundColor);  
        v.setImageBitmap(bm);  
        mDragBitmap = bm;  
        mWindowManager = (WindowManager)context.getSystemService("window");  
        mWindowManager.addView(v, mWindowParams);  
        mDragView = v;  
    }  
      
    private void dragView(int x, int y) {  
        if (mRemoveMode == SLIDE) {  
            float alpha = 1.0f;  
            int width = mDragView.getWidth();  
            if (x > width / 2) {  
                alpha = ((float)(width - x)) / (width / 2);  
            }  
            mWindowParams.alpha = alpha;  
        }  
        if (mRemoveMode == FLING) {  
            mWindowParams.x = x;  
        }  
        mWindowParams.y = y - mDragPoint + mCoordOffset;  
        mWindowManager.updateViewLayout(mDragView, mWindowParams);  
    }  
      
    private void stopDragging() {  
        if (mDragView != null) {  
            WindowManager wm = (WindowManager)getContext().getSystemService("window");  
            wm.removeView(mDragView);  
            mDragView.setImageDrawable(null);  
            mDragView = null;  
        }  
        if (mDragBitmap != null) {  
            mDragBitmap.recycle();  
            mDragBitmap = null;  
        }  
    }  
      
    public void setDragListener(DragListener l) {  
        mDragListener = l;  
    }  
      
    public void setDropListener(DropListener l) {  
        mDropListener = l;  
    }  
      
    public void setRemoveListener(RemoveListener l) {  
        mRemoveListener = l;  
    }  
    public interface DragListener {  
        void drag(int from, int to);  
    }  
    public interface DropListener {  
        void drop(int from, int to);  
    }  
    public interface RemoveListener {  
        void remove(int which);  
    }  
}  

<com.and.DragListview.TouchInterceptor
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"       
        android:textSize="18sp"
        android:drawSelectorOnTop="false"
        android:fastScrollEnabled="true" />


还有这个:
http://www.eoeandroid.com/thread-61490-1-1.html

Android学习系列(12)--App列表之拖拽GridView
http://www.cnblogs.com/qianxudetianxia/archive/2011/06/20/2084886.html
  • draggable可拖动的ListView,并且支持行删除功能
  • 大小: 17.2 KB
  • draggable可拖动的ListView,并且支持行删除功能
  • 大小: 17 KB