在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 = 96;//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" />


如果想要实现源码音乐播放器那种顺畅的拖动效果,则需注意2点:

1.<!-- height of a normal list item in edit playlist mode -->
<dimen name="normal_height">48dip</dimen>
<!-- height of an expanded list item in edit playlist mode -->
<dimen name="expanded_height">96dip</dimen>

后者的高度要为前者的2倍。

2.item对应的布局要在listview的item的bottom位置,即:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout             xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="48dip"><com.android.weather.CityListItemLayout android:id="@+id/item_layout"    android:orientation="horizontal"    android:layout_width="match_parent"    android:layout_height="48dip"          android:gravity="center_vertical"    android:layout_alignParentBottom="true">。。。</com.android.weather.CityListItemLayout></RelativeLayout>


更多相关文章

  1. LayoutInflater源码分析
  2. android6.0 源码 系统应用之Music代码之类逻辑分析
  3. Android(安卓)源码的编译
  4. 【30篇突击 android】源码统计 十五
  5. Android之AsyncTask源码分析(第五篇:execute方法只能执行一次的原
  6. RxJava 的使用入门
  7. Android(安卓)setContentView() 详解
  8. android开发必备的一些网址
  9. Android中volley封装实践记录(二)

随机推荐

  1. Android shape 绘制图形的实例详解
  2. Android(安卓)2.2完全退出程序, 使用广播
  3. android 拍照 onCreate() 调用两次的问题
  4. Android 状态栏全透明策略
  5. android Application学习之一
  6. android之GSON解析JSON
  7. Android常见监听事件
  8. Android 助力云计算
  9. android listview继承BaseAdapter,自定义
  10. EditText支持Search按键搜索