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

时间:2022-07-04 21:59:45
看图,拖动前: 
拖动的ListView,并且支持行删除功能 
拖动后: 
拖动的ListView,并且支持行删除功能 

Java代码   拖动的ListView,并且支持行删除功能
  1. package com.ql.view;  
  2.   
  3. import com.ql.activity.R;  
  4.   
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.PixelFormat;  
  8. import android.graphics.Rect;  
  9. import android.util.AttributeSet;  
  10. import android.util.Log;  
  11. import android.view.Gravity;  
  12. import android.view.MotionEvent;  
  13. import android.view.View;  
  14. import android.view.ViewConfiguration;  
  15. import android.view.ViewGroup;  
  16. import android.view.WindowManager;  
  17. import android.widget.AdapterView;  
  18. import android.widget.ImageView;  
  19. import android.widget.ListView;  
  20.   
  21. /** 
  22.  * draggable可拖动的列表,并且支持行删除功能 
  23.  * @author admin 
  24.  * 
  25.  */  
  26. public class DraggableListView extends ListView {  
  27.   
  28.     private DropListener mDropListener;  
  29.   
  30.     private ImageView mDragView;  
  31.     private int mDragPos; // which item is being dragged  
  32.     private int mFirstDragPos; // where was the dragged item originally  
  33.     private int mDragPoint; // at what offset inside the item did the user grab  
  34.                             // it  
  35.     private int mCoordOffset; // the difference between screen coordinates and  
  36.                                 // coordinates in this view  
  37.   
  38.     private Rect mTempRect = new Rect();  
  39.     private final int mTouchSlop;  
  40.     private int mHeight;  
  41.     private int mUpperBound;  
  42.     private int mLowerBound;  
  43.     private WindowManager mWindowManager;  
  44.     private WindowManager.LayoutParams mWindowParams;  
  45.     private int dragndropBackgroundColor = 0x00000000;  
  46.     private Bitmap mDragBitmap;  
  47.     private int mItemHeightHalf = 32;  
  48.     private int mItemHeightNormal = 64;  
  49.     private int mItemHeightExpanded = 128;  
  50.     //private int grabberId=-1;  
  51.   
  52.     public DraggableListView(Context context, AttributeSet attrs) {  
  53.         this(context, attrs, 0);  
  54.         // TODO Auto-generated constructor stub  
  55.     }  
  56.   
  57.     public DraggableListView(Context context, AttributeSet attrs, int defStyle) {  
  58.         super(context, attrs, defStyle);  
  59.         // TODO Auto-generated constructor stub  
  60.         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();  
  61.           
  62. //      if (attrs!=null) {  
  63. //          TypedArray a=getContext().obtainStyledAttributes(attrs,R.styleable.TouchListView,0, 0);  
  64. //  
  65. //          mItemHeightNormal=a.getDimensionPixelSize(R.styleable.TouchListView_normal_height, 0);  
  66. //          mItemHeightExpanded=a.getDimensionPixelSize(R.styleable.TouchListView_expanded_height, mItemHeightNormal);  
  67. //          grabberId=a.getResourceId(R.styleable.TouchListView_grabber, -1);  
  68. //          dragndropBackgroundColor=a.getColor(R.styleable.TouchListView_dragndrop_background, 0x00000000);  
  69. //          //mRemoveMode=a.getInt(R.styleable.TouchListView_remove_mode, -1);  
  70. //  
  71. //          a.recycle();  
  72. //      }  
  73.   
  74.     }  
  75.   
  76.     @Override  
  77.     public boolean onTouchEvent(MotionEvent ev) {  
  78.         // TODO Auto-generated method stub  
  79. //      Log.v(">>>>>>>>>>onTouchEvent", ">>>>>>>>>>onTouchEvent");  
  80.         if ((mDropListener != null) && mDragView != null) {  
  81.             int action = ev.getAction();  
  82.             switch (action) {  
  83.             case MotionEvent.ACTION_UP:  
  84.             case MotionEvent.ACTION_CANCEL:  
  85.                 Rect r = mTempRect;  
  86.                 mDragView.getDrawingRect(r);  
  87.                 stopDragging();  
  88.                 if (mDropListener != null && mDragPos >= 0  
  89.                         && mDragPos < getCount()) {  
  90.                     mDropListener.drop(mFirstDragPos, mDragPos);  
  91.                 }  
  92.                 unExpandViews(false);  
  93.                 break;  
  94.   
  95.             case MotionEvent.ACTION_DOWN:  
  96.             case MotionEvent.ACTION_MOVE:  
  97.                 int x = (int) ev.getX();  
  98.                 int y = (int) ev.getY();  
  99.                 dragView(x, y);  
  100.   
  101.                 int itemnum = getItemForPosition(y);  
  102.                 if (itemnum >= 0) {  
  103.                     if (action == MotionEvent.ACTION_DOWN  
  104.                             || itemnum != mDragPos) {  
  105.   
  106.                         mDragPos = itemnum;  
  107.                         doExpansion();  
  108. //                      Log.v(">>>doExpansion", ">>>>>>>>>>doExpansion");  
  109.                     }  
  110.                     /* 
  111.                     int speed = 0; 
  112.                     adjustScrollBounds(y); 
  113.                     if (y > mLowerBound) { 
  114.                         // scroll the list up a bit 
  115.                         speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4; 
  116.                     } else if (y < mUpperBound) { 
  117.                         // scroll the list down a bit 
  118.                         speed = y < mUpperBound / 2 ? -16 : -4; 
  119.                     } 
  120.                     if (speed != 0) { 
  121.                         int ref = pointToPosition(0, mHeight / 2); 
  122.                         if (ref == AdapterView.INVALID_POSITION) { 
  123.                             // we hit a divider or an invisible view, check 
  124.                             // somewhere else 
  125.                             ref = pointToPosition(0, mHeight / 2 
  126.                                     + getDividerHeight() + 64); 
  127.                         } 
  128.                         View v = getChildAt(ref - getFirstVisiblePosition()); 
  129.                         if (v != null) { 
  130.                             int pos = v.getTop(); 
  131.                             setSelectionFromTop(ref, pos - speed); 
  132.  
  133.                         } 
  134.                     } 
  135.                     */  
  136.                 }  
  137.                 break;  
  138.             }  
  139.             return true;  
  140.         }  
  141.         return super.onTouchEvent(ev);  
  142.   
  143.     }  
  144.   
  145.     @Override  
  146.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  147.         // TODO Auto-generated method stub  
  148.         if (mDropListener != null) {  
  149.             switch (ev.getAction()) {  
  150.             case MotionEvent.ACTION_DOWN:  
  151.                 int x = (int) ev.getX();  
  152.                 int y = (int) ev.getY();  
  153.                 int itemnum = pointToPosition(x, y);  
  154. //              Log.v("itemnum>>>", ">>>>>>>>" + itemnum);  
  155.                 if (itemnum == AdapterView.INVALID_POSITION) {  
  156.                     break;  
  157.                 }  
  158.                 ViewGroup item = (ViewGroup) getChildAt(itemnum  
  159.                         - getFirstVisiblePosition());  
  160. //              Log.v("itemnum>>>", ">>>>>>>>" + getFirstVisiblePosition()  
  161. //                      + "---" + ev.getRawY() + "----" + ev.getY()+"-----"+item.getTop());  
  162.                 mDragPoint = y - item.getTop();  
  163.                 mCoordOffset = ((int) ev.getRawY()) - y;  
  164.                 View dragger = item.findViewById(R.id.iconimg);//拖动的ImageView  
  165.                 Rect r = mTempRect;  
  166.                 // dragger.getDrawingRect(r);  
  167.   
  168.                 r.left = dragger.getLeft();  
  169.                 r.right = dragger.getRight();  
  170.                 r.top = dragger.getTop();  
  171.                 r.bottom = dragger.getBottom();  
  172.   
  173.                 if ((r.left < x) && (x < r.right)) {  
  174.                     item.setDrawingCacheEnabled(true);  
  175.                     // Create a copy of the drawing cache so that it does not  
  176.                     // get recycled  
  177.                     // by the framework when the list tries to clean up memory  
  178.                     Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());  
  179.                     startDragging(bitmap, y);  
  180.                     mDragPos = itemnum;  
  181.                     mFirstDragPos = mDragPos;  
  182.                     mHeight = getHeight();  
  183.                     int touchSlop = mTouchSlop;  
  184.                     mUpperBound = Math.min(y - touchSlop, mHeight / 3);  
  185.                     mLowerBound = Math.max(y + touchSlop, mHeight * 2 / 3);  
  186.                     return false;  
  187.                 }  
  188.                 //  
  189.                 View delView = item.findViewById(R.id.delete);//删除的ImageView  
  190.                 r.left = delView.getLeft();  
  191.                 r.right = delView.getRight();  
  192.                 r.top = delView.getTop();  
  193.                 r.bottom = delView.getBottom();  
  194.                 if ((r.left < x) && (x < r.right)) {  
  195.                     mDropListener.onDeleteClicked(itemnum);  
  196.                     return false;  
  197.                 }  
  198.   
  199.                 mDragView = null;  
  200.                 break;  
  201.             }  
  202.         }  
  203.         return super.onInterceptTouchEvent(ev);  
  204.     }  
  205.   
  206.     private void startDragging(Bitmap bm, int y) {  
  207.         stopDragging();  
  208.   
  209.         mWindowParams = new WindowManager.LayoutParams();  
  210.         mWindowParams.gravity = Gravity.TOP;  
  211.         mWindowParams.x = 0;  
  212.         mWindowParams.y = y - mDragPoint + mCoordOffset;  
  213.   
  214.         mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;  
  215.         mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;  
  216.         mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  
  217.                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE  
  218.                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  
  219.                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;  
  220.         mWindowParams.format = PixelFormat.TRANSLUCENT;  
  221.         mWindowParams.windowAnimations = 0;  
  222.   
  223.         ImageView v = new ImageView(getContext());  
  224.         // int backGroundColor =  
  225.         // getContext().getResources().getColor(R.color.dragndrop_background);  
  226.         v.setBackgroundColor(dragndropBackgroundColor);  
  227.         v.setImageBitmap(bm);  
  228.         mDragBitmap = bm;  
  229.   
  230.         mWindowManager = (WindowManager) getContext()  
  231.                 .getSystemService("window");  
  232.         mWindowManager.addView(v, mWindowParams);  
  233.         mDragView = v;  
  234.     }  
  235.   
  236.     private void stopDragging() {  
  237.         if (mDragView != null) {  
  238.             WindowManager wm = (WindowManager) getContext().getSystemService(  
  239.                     "window");  
  240.             wm.removeView(mDragView);  
  241.             mDragView.setImageDrawable(null);  
  242.             mDragView = null;  
  243.         }  
  244.         if (mDragBitmap != null) {  
  245.             mDragBitmap.recycle();  
  246.             mDragBitmap = null;  
  247.         }  
  248.     }  
  249.   
  250.     private void dragView(int x, int y) {  
  251.         float alpha = 1.0f;  
  252.         mWindowParams.alpha = alpha;  
  253.         // }  
  254.         mWindowParams.y = y - mDragPoint + mCoordOffset;  
  255.         mWindowManager.updateViewLayout(mDragView, mWindowParams);  
  256.     }  
  257.   
  258.     private int getItemForPosition(int y) {  
  259.         int adjustedy = y - mDragPoint - mItemHeightHalf;  
  260.         int pos = myPointToPosition(0, adjustedy);  
  261.         if (pos >= 0) {  
  262.             if (pos <= mFirstDragPos) {  
  263.                 pos += 1;  
  264.             }  
  265.         } else if (adjustedy < 0) {  
  266.             pos = 0;  
  267.         }  
  268.         return pos;  
  269.     }  
  270.   
  271.     private void adjustScrollBounds(int y) {  
  272.         if (y >= mHeight / 3) {  
  273.             mUpperBound = mHeight / 3;  
  274.         }  
  275.         if (y <= mHeight * 2 / 3) {  
  276.             mLowerBound = mHeight * 2 / 3;  
  277.         }  
  278.     }  
  279.   
  280.     /* 
  281.      * Restore size and visibility for all listitems 
  282.      */  
  283.     private void unExpandViews(boolean deletion) {  
  284.         for (int i = 0;; i++) {  
  285.             View v = getChildAt(i);  
  286.             if (v == null) {  
  287.                 if (deletion) {  
  288.                     // HACK force update of mItemCount  
  289.                     int position = getFirstVisiblePosition();  
  290.                     int y = getChildAt(0).getTop();  
  291.                     setAdapter(getAdapter());  
  292.                     setSelectionFromTop(position, y);  
  293.                     // end hack  
  294.                 }  
  295.                 layoutChildren(); // force children to be recreated where needed  
  296.                 v = getChildAt(i);  
  297.                 if (v == null) {  
  298.                     break;  
  299.                 }  
  300.             }  
  301.             ViewGroup.LayoutParams params = v.getLayoutParams();  
  302.             params.height = mItemHeightNormal;  
  303.             v.setLayoutParams(params);  
  304.             v.setVisibility(View.VISIBLE);  
  305.         }  
  306.     }  
  307.   
  308.     /* 
  309.      * Adjust visibility and size to make it appear as though an item is being 
  310.      * dragged around and other items are making room for it: If dropping the 
  311.      * item would result in it still being in the same place, then make the 
  312.      * dragged listitem's size normal, but make the item invisible. Otherwise, 
  313.      * if the dragged listitem is still on screen, make it as small as possible 
  314.      * and expand the item below the insert point. If the dragged item is not on 
  315.      * screen, only expand the item below the current insertpoint. 
  316.      */  
  317.     private void doExpansion() {  
  318.         int childnum = mDragPos - getFirstVisiblePosition();  
  319.         if (mDragPos > mFirstDragPos) {  
  320.             childnum++;  
  321.         }  
  322.   
  323.         View first = getChildAt(mFirstDragPos - getFirstVisiblePosition());  
  324.   
  325.         for (int i = 0;; i++) {  
  326.             View vv = getChildAt(i);  
  327.             if (vv == null) {  
  328.                 break;  
  329.             }  
  330.             int height = mItemHeightNormal;  
  331.             int visibility = View.VISIBLE;  
  332.             if (vv.equals(first)) {  
  333.                 // processing the item that is being dragged  
  334.                 if (mDragPos == mFirstDragPos) {  
  335.                     // hovering over the original location  
  336.                     visibility = View.INVISIBLE;  
  337.                 } else {  
  338.                     // not hovering over it  
  339.                     height = 1;  
  340.                 }  
  341.             } else if (i == childnum) {  
  342.                 if (mDragPos < getCount() - 1) {  
  343.                     height = mItemHeightExpanded;  
  344.                 }  
  345.             }  
  346.             ViewGroup.LayoutParams params = vv.getLayoutParams();  
  347.             params.height = height;  
  348.             vv.setLayoutParams(params);  
  349.             vv.setVisibility(visibility);  
  350.         }  
  351.     }  
  352.   
  353.     /* 
  354.      * pointToPosition() doesn't consider invisible views, but we need to, so 
  355.      * implement a slightly different version. 
  356.      */  
  357.     private int myPointToPosition(int x, int y) {  
  358.         Rect frame = mTempRect;  
  359.         final int count = getChildCount();  
  360.         for (int i = count - 1; i >= 0; i--) {  
  361.             final View child = getChildAt(i);  
  362.             child.getHitRect(frame);  
  363.             if (frame.contains(x, y)) {  
  364.                 return getFirstVisiblePosition() + i;  
  365.             }  
  366.         }  
  367.         return INVALID_POSITION;  
  368.     }  
  369.   
  370.     public interface DropListener {  
  371.         //  
  372.         void drop(int from, int to);  
  373.         //  
  374.         void onDeleteClicked(int index);  
  375.     }  
  376.   
  377.     public void setDropListener(DropListener onDrop) {  
  378.         // TODO Auto-generated method stub  
  379.         mDropListener = onDrop;  
  380.     }  
  381.   
  382. }  


使用: 
Java代码   拖动的ListView,并且支持行删除功能
  1. package com.ql.activity;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.HashMap;  
  5. import java.util.Map;  
  6.   
  7.   
  8. import android.app.Activity;  
  9. import android.app.AlertDialog;  
  10. import android.content.DialogInterface;  
  11. import android.os.Bundle;  
  12. import android.view.LayoutInflater;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.widget.ArrayAdapter;  
  16. import android.widget.TextView;  
  17.   
  18. import com.ql.view.DraggableListView;  
  19.   
  20.   
  21. public class Test_6_Activity  extends Activity{  
  22.     private DraggableListView   mListView;  
  23.     private DraggableArrayAdapter adapter = null;  
  24.     private ArrayList<Map<String, String>> array;  
  25. //  private int mIndex;  
  26.     @Override  
  27.     public void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.test5);  
  30.           
  31.         mListView = (DraggableListView) findViewById(R.id.draggable_list);    
  32.         array = getData();  
  33.         adapter = new DraggableArrayAdapter();  
  34.         mListView.setAdapter(adapter);  
  35.           
  36.         mListView.setDropListener(onDrop);  
  37. //      mListView.getAdapter();  
  38. //      //列表点击事件处理  
  39. //        mListView.setOnItemClickListener(new OnItemClickListener() {  
  40. //  
  41. //          @Override  
  42. //          public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,  
  43. //                                  long arg3) {  
  44. //                
  45. //              //Toast.makeText(context, "Click "+arg2, Toast.LENGTH_SHORT).show();  
  46. //          }  
  47. //        });     
  48. //          
  49. //        mListView.setOnItemLongClickListener(new OnItemLongClickListener() {  
  50. //            
  51. //          @Override  
  52. //          public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int position,  
  53. //                  long id) {  
  54. //              mIndex = position;  
  55. //              return false;  
  56. //          }  
  57. //        });  
  58.       
  59.     }  
  60.     //初始化数据  
  61.     private ArrayList<Map<String, String>> getData() {  
  62.         ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();  
  63.         for(int i=0; i<5; i++) {  
  64.             Map<String, String> map = new HashMap<String, String>();  
  65.             map.put("code""code"+i);  
  66.             map.put("name""name"+i);  
  67.             list.add(map);  
  68.         }  
  69.         return list;  
  70.     }  
  71.   
  72.     private DraggableListView.DropListener onDrop = new DraggableListView.DropListener() {  
  73.         @Override  
  74.         public void drop(int from, int to) {  
  75.             Map<String, String> item = adapter.getItem(from);  
  76.             adapter.remove(item);  
  77.             adapter.insert(item, to);  
  78.         }  
  79.   
  80.         @Override  
  81.         public void onDeleteClicked(int index) {  
  82. //          mIndex = index;  
  83.             delete(index);  
  84.         }  
  85.     };  
  86.     private void delete(final int index) {  
  87.         String prompt = "delete "+array.get(index).get("name").toString()+" "+array.get(index).get("code").toString()+"?";  
  88.         //删除确认对话          
  89.         new AlertDialog.Builder(Test_6_Activity.this)  
  90.             .setTitle("删除?")  
  91.             //.setIcon(android.R.drawable.ic_menu_help)  
  92.             .setMessage(prompt)  
  93.             .setCancelable(true)  
  94.             .setPositiveButton("确定"new DialogInterface.OnClickListener() {  
  95.                   
  96.                 @Override  
  97.                 public void onClick(DialogInterface dialog, int which) {  
  98.                     Map<String, String> item = adapter.getItem(index);  
  99.                     adapter.remove(item);  
  100.                 }  
  101.             })  
  102.             .setNegativeButton("取消"new DialogInterface.OnClickListener() {  
  103.                   
  104.                 @Override  
  105.                 public void onClick(DialogInterface dialog, int which) {  
  106.                     dialog.cancel();  
  107.                 }  
  108.             }).show();  
  109.   
  110.     }  
  111.     /** 
  112.      * 适配器 
  113.      * @author admin 
  114.      * 
  115.      */  
  116.     class DraggableArrayAdapter extends ArrayAdapter<Map<String, String>> {  
  117.   
  118.         DraggableArrayAdapter() {  
  119.               
  120.             super(Test_6_Activity.this, R.layout.row_simple_list_item_4, array);  
  121.         }  
  122.   
  123.         public ArrayList<Map<String, String>> getList() {  
  124.             return array;  
  125.         }  
  126.   
  127.         public View getView(int position, View convertView, ViewGroup parent) {  
  128.               
  129.             View row = convertView;  
  130.             if (row == null) {  
  131.                 LayoutInflater inflater = getLayoutInflater();  
  132.                 row = inflater.inflate(R.layout.row_simple_list_item_4, parent, false);  
  133.             }  
  134.             TextView code = (TextView) row.findViewById(R.id.code);  
  135.             code.setText(array.get(position).get("code").toString());  
  136.             TextView name = (TextView) row.findViewById(R.id.name);  
  137.             name.setText(array.get(position).get("name").toString());  
  138.   
  139.             return (row);  
  140.         }  
  141.     }  
  142. }  


text5.xml布局文件: 
Xml代码   拖动的ListView,并且支持行删除功能
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent">  
  6.   
  7.     <com.ql.view.DraggableListView  
  8.         android:id="@+id/draggable_list"  
  9.         android:layout_width="fill_parent"   
  10.         android:layout_height="fill_parent"  
  11.         />  
  12. </LinearLayout>  

适配器中使用的布局文件row_simple_list_item_4.xml: 
Xml代码   拖动的ListView,并且支持行删除功能
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="wrap_content"  
  5.     >  
  6.     <!--  
  7.     android:background="@drawable/list_bg" 
  8.      -->  
  9.     <ImageView android:id="@+id/iconimg"  
  10.         android:layout_alignParentLeft="true"  
  11.         android:layout_alignParentTop="true"  
  12.         android:layout_alignParentBottom="true"  
  13.         android:layout_width="wrap_content"  
  14.         android:layout_height="wrap_content"  
  15.         android:src="@drawable/grabber"  
  16.         />  
  17.           
  18.     <ImageView android:id="@+id/delete"  
  19.         android:layout_alignParentRight="true"  
  20.         android:layout_centerVertical="true"  
  21.         android:layout_width="wrap_content"  
  22.         android:layout_height="wrap_content"  
  23.         android:paddingRight="5dip"  
  24.         android:src="@android:drawable/ic_delete"  
  25.         />  
  26.           
  27.     <TextView android:id="@+id/code"  
  28.         android:layout_width="wrap_content"  
  29.         android:layout_height="wrap_content"  
  30.         android:paddingLeft="10dip"  
  31.         android:layout_toRightOf="@id/iconimg"  
  32.         android:layout_centerVertical="true"  
  33.         android:textSize="20dip"  
  34.         android:textColor="#888888"  
  35.         />  
  36.     <TextView android:id="@+id/name"  
  37.         android:layout_width="wrap_content"  
  38.         android:layout_height="wrap_content"  
  39.         android:paddingLeft="10dip"  
  40.         android:layout_toRightOf="@id/code"  
  41.         android:layout_centerVertical="true"  
  42.         android:textSize="20dip"  
  43.         android:textColor="#888888"  
  44.         />  
  45.           
  46. </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的拖动效果,并提供接口,在程序接口中实现数据的交换即可。 
Java代码   拖动的ListView,并且支持行删除功能
  1. package com.and.DragListview;    
  2. import java.util.ArrayList;    
  3. import java.util.List;    
  4. import android.app.ListActivity;    
  5. import android.content.Context;    
  6. import android.os.Bundle;    
  7. import android.view.LayoutInflater;    
  8. import android.view.View;    
  9. import android.view.ViewGroup;    
  10. import android.widget.BaseAdapter;    
  11. import android.widget.ImageView;    
  12. import android.widget.TextView;    
  13. public class DragListview extends ListActivity {       
  14.     MyAdapter adapter;    
  15.     TouchInterceptor list;    
  16.     List<String> arrayText;    
  17.         
  18.     @Override    
  19.     public void onCreate(Bundle savedInstanceState) {    
  20.         super.onCreate(savedInstanceState);    
  21.         setContentView(R.layout.main);    
  22.             
  23.         list = (TouchInterceptor) getListView();//(TouchInterceptor)findViewById(android.R.id.list);    
  24.         getText();    
  25.             
  26.         adapter = new MyAdapter(this);    
  27.         setListAdapter(adapter);    
  28.            
  29.         list.setDropListener(mDropListener);    
  30.      //   list.setRemoveListener(mRemoveListener);          
  31.     }    
  32.     public void getText(){    
  33.         arrayText = new ArrayList<String>();    
  34.         arrayText.add("传奇");    
  35.         arrayText.add("红豆");    
  36.         arrayText.add("流年");    
  37.         arrayText.add("棋子");    
  38.     }    
  39.         
  40.     //交换listview的数据    
  41.     private TouchInterceptor.DropListener mDropListener =    
  42.         new TouchInterceptor.DropListener() {    
  43.         public void drop(int from, int to) {    
  44.             String item = arrayText.get(from);    
  45.             arrayText.remove(item);//.remove(from);    
  46.             arrayText.add(to, item);    
  47.             adapter.notifyDataSetChanged();    
  48.         }    
  49.     };    
  50.         
  51.     private TouchInterceptor.RemoveListener mRemoveListener =    
  52.         new TouchInterceptor.RemoveListener() {    
  53.         public void remove(int which) {              
  54.         }    
  55.     };    
  56.         
  57.     class MyAdapter extends BaseAdapter{    
  58.         private LayoutInflater mInflater;    
  59.         Context mContext;    
  60.         public MyAdapter(Context c){    
  61.             mInflater = LayoutInflater.from(c);    
  62.         }    
  63.         public int getCount() {             
  64.             return arrayText.size();    
  65.         }    
  66.         public Object getItem(int arg0) {    
  67.             return arrayText.get(arg0);    
  68.         }    
  69.         public long getItemId(int arg0) {    
  70.             return arg0;    
  71.         }    
  72.         public View getView(int arg0, View contentView, ViewGroup arg2) {    
  73.             ImageView img;    
  74.             TextView text;    
  75.             if(contentView==null){    
  76.                 contentView = mInflater.inflate(R.layout.list_layout, null);     
  77.                 //contentView = mInflater.inflate(R.layout.list_layout,null);    
  78.             }    
  79.             img = (ImageView)contentView.findViewById(R.id.img);    
  80.             img.setBackgroundResource(R.drawable.icon);    
  81.             text = (TextView)contentView.findViewById(R.id.text);    
  82.             text.setText(arrayText.get(arg0).toString());    
  83.                 
  84.             return contentView;    
  85.         }    
  86.             
  87.     }    
  88. }    

Java代码   拖动的ListView,并且支持行删除功能
  1. /*  
  2.  * Copyright (C) 2008 The Android Open Source Project  
  3.  *  
  4.  * Licensed under the Apache License, Version 2.0 (the "License");  
  5.  * you may not use this file except in compliance with the License.  
  6.  * You may obtain a copy of the License at  
  7.  *  
  8.  *      http://www.apache.org/licenses/LICENSE-2.0  
  9.  *  
  10.  * Unless required by applicable law or agreed to in writing, software  
  11.  * distributed under the License is distributed on an "AS IS" BASIS,  
  12.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
  13.  * See the License for the specific language governing permissions and  
  14.  * limitations under the License.  
  15.  */    
  16. package com.and.DragListview;    
  17. import android.content.Context;    
  18. import android.content.SharedPreferences;    
  19. import android.content.res.Resources;    
  20. import android.graphics.Bitmap;    
  21. import android.graphics.PixelFormat;    
  22. import android.graphics.Rect;    
  23. import android.util.AttributeSet;    
  24. import android.view.GestureDetector;    
  25. import android.view.Gravity;    
  26. import android.view.MotionEvent;    
  27. import android.view.View;    
  28. import android.view.ViewConfiguration;    
  29. import android.view.ViewGroup;    
  30. import android.view.WindowManager;    
  31. import android.view.GestureDetector.SimpleOnGestureListener;    
  32. import android.widget.AdapterView;    
  33. import android.widget.ImageView;    
  34. import android.widget.ListView;    
  35. public class TouchInterceptor extends ListView {    
  36.         
  37.     private ImageView mDragView;    
  38.     private WindowManager mWindowManager;    
  39.     private WindowManager.LayoutParams mWindowParams;    
  40.     private int mDragPos;      // which item is being dragged    
  41.     private int mFirstDragPos; // where was the dragged item originally    
  42.     private int mDragPoint;    // at what offset inside the item did the user grab it    
  43.     private int mCoordOffset;  // the difference between screen coordinates and coordinates in this view    
  44.     private DragListener mDragListener;    
  45.     private DropListener mDropListener;    
  46.     private RemoveListener mRemoveListener;    
  47.     private int mUpperBound;    
  48.     private int mLowerBound;    
  49.     private int mHeight;    
  50.     private GestureDetector mGestureDetector;    
  51.     private static final int FLING = 0;    
  52.     private static final int SLIDE = 1;    
  53.     private int mRemoveMode = -1;    
  54.     private Rect mTempRect = new Rect();    
  55.     private Bitmap mDragBitmap;    
  56.     private final int mTouchSlop;    
  57.     private int mItemHeightNormal;    
  58.     private int mItemHeightExpanded;    
  59.     private int mItemHeightHalf;    
  60.     public TouchInterceptor(Context context, AttributeSet attrs) {    
  61.         super(context, attrs);    
  62.         SharedPreferences pref = context.getSharedPreferences("Music"3);    
  63.         mRemoveMode = pref.getInt("deletemode", -1);    
  64.         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();    
  65.         Resources res = getResources();    
  66.         mItemHeightNormal = 48;//res.getDimensionPixelSize(R.dimen.normal_height);    
  67.         mItemHeightHalf = mItemHeightNormal / 2;    
  68.         mItemHeightExpanded = 48;//res.getDimensionPixelSize(R.dimen.expanded_height);    
  69.     }    
  70.         
  71.     @Override    
  72.     public boolean onInterceptTouchEvent(MotionEvent ev) {    
  73.         if (mRemoveListener != null && mGestureDetector == null) {    
  74.             if (mRemoveMode == FLING) {    
  75.                 mGestureDetector = new GestureDetector(getContext(), new SimpleOnGestureListener() {    
  76.                     @Override    
  77.                     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,    
  78.                             float velocityY) {    
  79.                         if (mDragView != null) {    
  80.                             if (velocityX > 1000) {    
  81.                                 Rect r = mTempRect;    
  82.                                 mDragView.getDrawingRect(r);    
  83.                                 if ( e2.getX() > r.right * 2 / 3) {    
  84.                                     // fast fling right with release near the right edge of the screen    
  85.                                     stopDragging();    
  86.                                     mRemoveListener.remove(mFirstDragPos);    
  87.                                     unExpandViews(true);    
  88.                                 }    
  89.                             }    
  90.                             // flinging while dragging should have no effect    
  91.                             return true;    
  92.                         }    
  93.                         return false;    
  94.                     }    
  95.                 });    
  96.             }    
  97.         }    
  98.         if (mDragListener != null || mDropListener != null) {    
  99.             switch (ev.getAction()) {    
  100.                 case MotionEvent.ACTION_DOWN:    
  101.                     int x = (int) ev.getX();    
  102.                     int y = (int) ev.getY();    
  103.                     int itemnum = pointToPosition(x, y);    
  104.                     if (itemnum == AdapterView.INVALID_POSITION) {    
  105.                         break;    
  106.                     }    
  107.                     ViewGroup item = (ViewGroup) getChildAt(itemnum - getFirstVisiblePosition());    
  108.                     mDragPoint = y - item.getTop();    
  109.                     mCoordOffset = ((int)ev.getRawY()) - y;    
  110.                     View dragger = item.findViewById(R.id.img);//..........................    
  111.                     Rect r = mTempRect;    
  112.                     dragger.getDrawingRect(r);    
  113.                     // The dragger icon itself is quite small, so pretend the touch area is bigger    
  114.                     if (x < r.right * 2) {    
  115.                         item.setDrawingCacheEnabled(true);    
  116.                         // Create a copy of the drawing cache so that it does not get recycled    
  117.                         // by the framework when the list tries to clean up memory    
  118.                         Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());    
  119.                         startDragging(bitmap, y);    
  120.                         mDragPos = itemnum;    
  121.                         mFirstDragPos = mDragPos;    
  122.                         mHeight = getHeight();    
  123.                         int touchSlop = mTouchSlop;    
  124.                         mUpperBound = Math.min(y - touchSlop, mHeight / 3);    
  125.                         mLowerBound = Math.max(y + touchSlop, mHeight * 2 /3);    
  126.                         return false;    
  127.                     }    
  128.                     stopDragging();    
  129.                     break;    
  130.             }    
  131.         }    
  132.         return super.onInterceptTouchEvent(ev);    
  133.     }    
  134.         
  135.     /*  
  136.      * pointToPosition() doesn't consider invisible views, but we  
  137.      * need to, so implement a slightly different version.  
  138.      */    
  139.     private int myPointToPosition(int x, int y) {    
  140.         if (y < 0) {    
  141.             // when dragging off the top of the screen, calculate position    
  142.             // by going back from a visible item    
  143.             int pos = myPointToPosition(x, y + mItemHeightNormal);    
  144.             if (pos > 0) {    
  145.                 return pos - 1;    
  146.             }    
  147.         }    
  148.         Rect frame = mTempRect;    
  149.         final int count = getChildCount();    
  150.         for (int i = count - 1; i >= 0; i--) {    
  151.             final View child = getChildAt(i);    
  152.             child.getHitRect(frame);    
  153.             if (frame.contains(x, y)) {    
  154.                 return getFirstVisiblePosition() + i;    
  155.             }    
  156.         }    
  157.         return INVALID_POSITION;    
  158.     }    
  159.         
  160.     private int getItemForPosition(int y) {    
  161.         int adjustedy = y - mDragPoint - mItemHeightHalf;    
  162.         int pos = myPointToPosition(0, adjustedy);    
  163.         if (pos >= 0) {    
  164.             if (pos <= mFirstDragPos) {    
  165.                 pos += 1;    
  166.             }    
  167.         } else if (adjustedy < 0) {    
  168.             // this shouldn't happen anymore now that myPointToPosition deals    
  169.             // with this situation    
  170.             pos = 0;    
  171.         }    
  172.         return pos;    
  173.     }    
  174.         
  175.     private void adjustScrollBounds(int y) {    
  176.         if (y >= mHeight / 3) {    
  177.             mUpperBound = mHeight / 3;    
  178.         }    
  179.         if (y <= mHeight * 2 / 3) {    
  180.             mLowerBound = mHeight * 2 / 3;    
  181.         }    
  182.     }    
  183.     /*  
  184.      * Restore size and visibility for all listitems  
  185.      */    
  186.     private void unExpandViews(boolean deletion) {    
  187.         for (int i = 0;; i++) {    
  188.             View v = getChildAt(i);    
  189.             if (v == null) {    
  190.                 if (deletion) {    
  191.                     // HACK force update of mItemCount    
  192.                     int position = getFirstVisiblePosition();    
  193.                     int y = getChildAt(0).getTop();    
  194.                     setAdapter(getAdapter());    
  195.                     setSelectionFromTop(position, y);    
  196.                     // end hack    
  197.                 }    
  198.                 layoutChildren(); // force children to be recreated where needed    
  199.                 v = getChildAt(i);    
  200.                 if (v == null) {    
  201.                     break;    
  202.                 }    
  203.             }    
  204.             ViewGroup.LayoutParams params = v.getLayoutParams();    
  205.             params.height = mItemHeightNormal;    
  206.             v.setLayoutParams(params);    
  207.             v.setVisibility(View.VISIBLE);    
  208.         }    
  209.     }    
  210.         
  211.     /* Adjust visibility and size to make it appear as though  
  212.      * an item is being dragged around and other items are making  
  213.      * room for it:  
  214.      * If dropping the item would result in it still being in the  
  215.      * same place, then make the dragged listitem's size normal,  
  216.      * but make the item invisible.  
  217.      * Otherwise, if the dragged listitem is still on screen, make  
  218.      * it as small as possible and expand the item below the insert  
  219.      * point.  
  220.      * If the dragged item is not on screen, only expand the item  
  221.      * below the current insertpoint.  
  222.      */    
  223.     private void doExpansion() {    
  224.         int childnum = mDragPos - getFirstVisiblePosition();    
  225.         if (mDragPos > mFirstDragPos) {    
  226.             childnum++;    
  227.         }    
  228.         View first = getChildAt(mFirstDragPos - getFirstVisiblePosition());    
  229.         for (int i = 0;; i++) {    
  230.             View vv = getChildAt(i);    
  231.             if (vv == null) {    
  232.                 break;    
  233.             }    
  234.             int height = mItemHeightNormal;    
  235.             int visibility = View.VISIBLE;    
  236.             if (vv.equals(first)) {    
  237.                 // processing the item that is being dragged    
  238.                 if (mDragPos == mFirstDragPos) {    
  239.                     // hovering over the original location    
  240.                     visibility = View.INVISIBLE;    
  241.                 } else {    
  242.                     // not hovering over it    
  243.                     height = 1;    
  244.                 }    
  245.             } else if (i == childnum) {    
  246.                 if (mDragPos < getCount() - 1) {    
  247.                     height = mItemHeightExpanded;    
  248.                 }    
  249.             }    
  250.             ViewGroup.LayoutParams params = vv.getLayoutParams();    
  251.             params.height = height;    
  252.             vv.setLayoutParams(params);    
  253.             vv.setVisibility(visibility);    
  254.         }    
  255.     }    
  256.         
  257.     @Override    
  258.     public boolean onTouchEvent(MotionEvent ev) {    
  259.         if (mGestureDetector != null) {    
  260.             mGestureDetector.onTouchEvent(ev);    
  261.         }    
  262.         if ((mDragListener != null || mDropListener != null) && mDragView != null) {    
  263.             int action = ev.getAction();     
  264.             switch (action) {    
  265.                 case MotionEvent.ACTION_UP:    
  266.                 case MotionEvent.ACTION_CANCEL:    
  267.                     Rect r = mTempRect;    
  268.                     mDragView.getDrawingRect(r);    
  269.                     stopDragging();    
  270.                     if (mRemoveMode == SLIDE && ev.getX() > r.right * 3 / 4) {    
  271.                         if (mRemoveListener != null) {    
  272.                             mRemoveListener.remove(mFirstDragPos);    
  273.                         }    
  274.                         unExpandViews(true);    
  275.                     } else {    
  276.                         if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount()) {    
  277.                             mDropListener.drop(mFirstDragPos, mDragPos);    
  278.                         }    
  279.                         unExpandViews(false);    
  280.                     }    
  281.                     break;    
  282.                         
  283.                 case MotionEvent.ACTION_DOWN:    
  284.                 case MotionEvent.ACTION_MOVE:    
  285.                     int x = (int) ev.getX();    
  286.                     int y = (int) ev.getY();    
  287.                     dragView(x, y);    
  288.                     int itemnum = getItemForPosition(y);    
  289.                     if (itemnum >= 0) {    
  290.                         if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {    
  291.                             if (mDragListener != null) {    
  292.                                 mDragListener.drag(mDragPos, itemnum);    
  293.                             }    
  294.                             mDragPos = itemnum;    
  295.                             doExpansion();    
  296.                         }    
  297.                         int speed = 0;    
  298.                         adjustScrollBounds(y);    
  299.                         if (y > mLowerBound) {    
  300.                             // scroll the list up a bit    
  301.                             speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;    
  302.                         } else if (y < mUpperBound) {    
  303.                             // scroll the list down a bit    
  304.                             speed = y < mUpperBound / 2 ? -16 : -4;    
  305.                         }    
  306.                         if (speed != 0) {    
  307.                             int ref = pointToPosition(0, mHeight / 2);    
  308.                             if (ref == AdapterView.INVALID_POSITION) {    
  309.                                 //we hit a divider or an invisible view, check somewhere else    
  310.                                 ref = pointToPosition(0, mHeight / 2 + getDividerHeight() + 64);    
  311.                             }    
  312.                             View v = getChildAt(ref - getFirstVisiblePosition());    
  313.                             if (v!= null) {    
  314.                                 int pos = v.getTop();    
  315.                                 setSelectionFromTop(ref, pos - speed);    
  316.                             }    
  317.                         }    
  318.                     }    
  319.                     break;    
  320.             }    
  321.             return true;    
  322.         }    
  323.         return super.onTouchEvent(ev);    
  324.     }    
  325.         
  326.     private void startDragging(Bitmap bm, int y) {    
  327.         stopDragging();    
  328.         mWindowParams = new WindowManager.LayoutParams();    
  329.         mWindowParams.gravity = Gravity.TOP;    
  330.         mWindowParams.x = 0;    
  331.         mWindowParams.y = y - mDragPoint + mCoordOffset;    
  332.         mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;    
  333.         mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;    
  334.         mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE    
  335.                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE    
  336.                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON    
  337.                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN    
  338.                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;    
  339.         mWindowParams.format = PixelFormat.TRANSLUCENT;    
  340.         mWindowParams.windowAnimations = 0;    
  341.             
  342.         Context context = getContext();    
  343.         ImageView v = new ImageView(context);    
  344. //        int backGroundColor = context.getResources().getColor(R.color.dragndrop_background);    
  345. //        v.setBackgroundColor(backGroundColor);    
  346.         v.setImageBitmap(bm);    
  347.         mDragBitmap = bm;    
  348.         mWindowManager = (WindowManager)context.getSystemService("window");    
  349.         mWindowManager.addView(v, mWindowParams);    
  350.         mDragView = v;    
  351.     }    
  352.         
  353.     private void dragView(int x, int y) {    
  354.         if (mRemoveMode == SLIDE) {    
  355.             float alpha = 1.0f;    
  356.             int width = mDragView.getWidth();    
  357.             if (x > width / 2) {    
  358.                 alpha = ((float)(width - x)) / (width / 2);    
  359.             }    
  360.             mWindowParams.alpha = alpha;    
  361.         }    
  362.         if (mRemoveMode == FLING) {    
  363.             mWindowParams.x = x;    
  364.         }    
  365.         mWindowParams.y = y - mDragPoint + mCoordOffset;    
  366.         mWindowManager.updateViewLayout(mDragView, mWindowParams);    
  367.     }    
  368.         
  369.     private void stopDragging() {    
  370.         if (mDragView != null) {    
  371.             WindowManager wm = (WindowManager)getContext().getSystemService("window");    
  372.             wm.removeView(mDragView);    
  373.             mDragView.setImageDrawable(null);    
  374.             mDragView = null;    
  375.         }    
  376.         if (mDragBitmap != null) {    
  377.             mDragBitmap.recycle();    
  378.             mDragBitmap = null;    
  379.         }    
  380.     }    
  381.         
  382.     public void setDragListener(DragListener l) {    
  383.         mDragListener = l;    
  384.     }    
  385.         
  386.     public void setDropListener(DropListener l) {    
  387.         mDropListener = l;    
  388.     }    
  389.         
  390.     public void setRemoveListener(RemoveListener l) {    
  391.         mRemoveListener = l;    
  392.     }    
  393.     public interface DragListener {    
  394.         void drag(int from, int to);    
  395.     }    
  396.     public interface DropListener {    
  397.         void drop(int from, int to);    
  398.     }    
  399.     public interface RemoveListener {    
  400.         void remove(int which);    
  401.     }    
  402. }    

<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


转自:http://gundumw100.iteye.com/blog/919325