可以拖动的listview+限制拖动某一图片

可以拖动的listview+限制拖动某一图片

package com.coolwind.weather;

import java.lang.reflect.Field;

import android.app.Activity;
import android.app.Service;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.nfc.Tag;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;


public class SimpleDragListView extends ListView {
    private static final String TAG = "TAG_SimpleDragListView";

    private ImageView mDragView;
    private ImageView defaultview;
    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 SimpleListener mSimpleListener;
    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 int mItemHeightNormal;
    private int mItemHeightExpanded;
    private int mItemHeightHalf;
    private int mLinearDeleHeight;
    private int mOptionItem = -1;
    private boolean mOptionDelItem = false;
    private Context mContext;
    private int mStatusBarHeight = 0;
    //added by zhangyulin for CR00683126 start
    private int mUpperBound;
    private int mLowerBound;
    private int mHeight;
    private final int mTouchSlop;
    private int oneScreenCount;
    //added by zhangyulin for CR00683126 end
    public SimpleDragListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Resources res = getResources();
        mContext = context;
        mItemHeightNormal = res.getDimensionPixelSize(R.dimen.managecity_item_height);
        mItemHeightHalf = mItemHeightNormal / 2;
        mLinearDeleHeight = res.getDimensionPixelSize(R.dimen.manage_menulist_layout_height);
        mItemHeightExpanded = res.getDimensionPixelSize(R.dimen.managecity_item_height) * 2;
        try {
            Class<?> c = Class.forName("com.android.internal.R$dimen");
            Object obj = c.newInstance();
            Field field = c.getField("status_bar_height");
            int x = Integer.parseInt(field.get(obj).toString());
            int sbar = context.getResources().getDimensionPixelSize(x);
            mStatusBarHeight = sbar;
        } catch (Exception e1) {
            e1.printStackTrace();
        } 
         
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {

        if (mSimpleListener != 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();
                                            mSimpleListener
                                                    .remove(mFirstDragPos);
                                            unExpandViews(true);
                                        }
                                    }
                                    // flinging while dragging should
                                    // have no effect
                                    return true;
                                }
                                return false;
                            }
                        });
            }
        }
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            if (mSimpleListener != null) {
                int x = (int) ev.getX();
                // int y = (int) ev.getY();
                int y = (int) ev.getRawY();
                y = y - mStatusBarHeight;
                Log.d(TAG, "mStatusBarHeight=" + mStatusBarHeight);
                mOptionItem = pointToPosition(x, y - getTop());
                if (mOptionItem == AdapterView.INVALID_POSITION) {
                    return false;
                }
               
                ViewGroup item=(ViewGroup) getChildAt(mOptionItem- getFirstVisiblePosition());
                 
                int firstposition=getFirstVisiblePosition();
               int lastposition=getLastVisiblePosition();
               oneScreenCount=(lastposition-firstposition)+1;//added byzhangyulin at 2012.10.17
                Log.d(TAG,"getChildCount() = " + getChildCount() +"oneScreenCount="+oneScreenCount);   
                mDragPoint = y - item.getBottom() - getTop()
                        + mItemHeightNormal;
                mCoordOffset = ((int) ev.getRawY()) - y + getTop();
                View dragger = item.findViewById(R.id.managecity_list_dragimg);
                Rect r = mTempRect;
                r.left = dragger.getLeft();
                r.right = dragger.getRight();
                r.top = dragger.getTop();
                r.bottom = dragger.getBottom();
                if ((r.left < x) && (x < r.right)) {
                    mSimpleListener.visible(View.VISIBLE);
                    Vibrator vibrator = (Vibrator) mContext
                            .getSystemService(Service.VIBRATOR_SERVICE);
                    vibrator.vibrate(90);
                    if(0==mOptionItem){
                        defaultview = (ImageView) item.findViewById(R.id.weather_isDefault);
                        defaultview.setVisibility(View.GONE);
                    }
                    item.setDrawingCacheEnabled(true);
                    Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache());
                    item.destroyDrawingCache();
                    // startDragging(bitmap, y);
                    startDragging(bitmap, y + mStatusBarHeight);
                    mDragPos = mOptionItem;
                    mFirstDragPos = mDragPos;
                    // added by zhangyulin for CR00683126 start
                    mHeight = getHeight();
                    int touchSlop = mTouchSlop;
                    mUpperBound = Math.min(y - touchSlop, mHeight / 3);
                    mLowerBound = Math.max(y + touchSlop, mHeight * 2 / 3);
                    // added by zhangyulin for CR00683126 end
                    Object temObject=getItemAtPosition(mFirstDragPos);
                    System.out.println("temObjecttemObjecttemObject"+temObject);
                    return false;
                }
                return true;
            }
            break;

        }
        return super.onInterceptTouchEvent(ev);
    }

  

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        Log.d("cng",".......");
        if (mGestureDetector != null) {
            mGestureDetector.onTouchEvent(ev);
        }
        if ((mSimpleListener != null) && mDragView != null) {
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_UP:
                    mSimpleListener.visible(View.INVISIBLE);
                    mSimpleListener.deleback(Color.DKGRAY);
                case MotionEvent.ACTION_CANCEL:
                    mSimpleListener.visible(View.INVISIBLE);
                    mSimpleListener.deleback(Color.DKGRAY);
                    Rect r = mTempRect;
                    mDragView.getDrawingRect(r);
                    stopDragging();
                   // float listBottom = getChildAt(getChildCount()-1).getBottom();  //最后一项底部边缘y值 办一张玉林
                    if (mRemoveMode == SLIDE && ev.getX() > r.right * 3 / 4) {
                        mSimpleListener.remove(mFirstDragPos);
                        unExpandViews(true);
                    } else {
                        if (mDragPos >= 0 && mDragPos < getCount()) {
                            if (mOptionDelItem == true) {
                                mSimpleListener.remove(mOptionItem);
                                mOptionDelItem = false;
                            } else {
                                Log.d(TAG, "mFirstDragPos = " +mFirstDragPos+"mDragPos = "+mDragPos);
                             
                                if(oneScreenCount==mDragPos){//added byzhangyulin at 2012.10.17
                                      mSimpleListener.drop(mFirstDragPos, mDragPos+1);
                                }else{
                                      mSimpleListener.drop(mFirstDragPos, mDragPos);
                                }
                            }
                        }
                        unExpandViews(false);
                    }
                   // if(0==mOptionItem){
                  /*      ViewGroup item=(ViewGroup) getChildAt(0);
                        defaultview = (ImageView) item.findViewById(R.id.weather_isDefault);
                        defaultview.setVisibility(View.VISIBLE);*/
                    //}
                    break;

                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:
                       Log.d("cng",".......");
                    int mx = (int) ev.getX();
                    int my = (int) ev.getY();               
                    dragView(mx, my);
                    int mitemnum = getItemForPosition(my);
                    if (mitemnum >= 0) {
                        if (action == MotionEvent.ACTION_DOWN || mitemnum != mDragPos) {
                            mSimpleListener.drag(mDragPos, mitemnum);
                            Log.d(TAG, "mitemnum = "+mitemnum);//8
                            Log.d(TAG, "mDragPos = "+mDragPos);//7
                            mDragPos = mitemnum;
                            doExpansion();
                        }
                    }
                  //added by zhangyulin for CR00683126 start
                    int speed = 0;
                    adjustScrollBounds(my);

                    if (my > mLowerBound) {
                        // scroll the list up a bit
                        if (getLastVisiblePosition() < getCount() - 1) {
                            speed = my > (mHeight + mLowerBound) / 2 ? 16 : 4;
                        } else {
                            speed = 1;
                        }
                    } else if (my < mUpperBound) {
                        // scroll the list down a bit
                        speed = my < mUpperBound / 2 ? -16 : -4;
                        if (getFirstVisiblePosition() == 0
                                && getChildAt(0).getTop() >= getPaddingTop()) {
                            // if we're already at the top, don't try to scroll,
                            // because
                            // it causes the framework to do some extra drawing that
                            // messes
                            // up our animation
                            speed = 0;
                        }
                    }
                    if (speed != 0) {
                        smoothScrollBy(speed, 30);
                    }
                    //added by zhangyulin for CR00683126 end
                    break;
            }
            return true;
        }
        return super.onTouchEvent(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 - mItemHeightNormal ;
        int pos = myPointToPosition(0, adjustedy);
         Log.d("cng","pos = " + pos + ",adjustedy = " + 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;
        }
       
        if ((y > mHeight - mItemHeightNormal)
                && (pos == getCount() - 2)
                && (y >= mFirstDragPos + mItemHeightNormal /3)) {
               pos += 1;
          }
        return pos;
    }

    /*
     * 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++;
        }
        Log.d(TAG,"childnum = " + 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) {
                 
                Log.d(TAG,"getCount() = " + getCount() +"mDragPos="+mDragPos);
                if (mDragPos < getCount() - 1) {
                    height = mItemHeightExpanded;
                }
                if(mDragPos ==oneScreenCount){
                    height = mItemHeightNormal;
                }
            }
            ViewGroup.LayoutParams params = vv.getLayoutParams();
            params.height = height;
            vv.setLayoutParams(params);
            vv.setVisibility(visibility);
        }
    }

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

        mWindowParams = new WindowManager.LayoutParams();
        mWindowParams.gravity = Gravity.TOP;
        mWindowParams.y = y - mItemHeightHalf;

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

        Context context = getContext();
        ImageView v = new ImageView(context);
        v.setImageBitmap(bm);
        mDragBitmap = bm;

        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        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) {//1/2
                alpha = ((float) (width - x)) / (width / 2);
            }
            mWindowParams.alpha = alpha;
        }
        if (mRemoveMode == FLING) {
            mWindowParams.x = x;
        }
        mWindowParams.y = y - mItemHeightHalf + mCoordOffset;
        if (mWindowParams.y <= mLinearDeleHeight) {
            mOptionDelItem = true;
            mSimpleListener.deleback(Color.RED);
        } else {
            mOptionDelItem = false;
            mSimpleListener.deleback(Color.DKGRAY);
        }
        mWindowManager.updateViewLayout(mDragView, mWindowParams);
    }

    private void stopDragging() {
        if (mDragView != null) {
            mWindowManager.removeView(mDragView);
            mDragView = null;
        }
        if (mDragBitmap != null) {
            mDragBitmap.recycle();
            mDragBitmap = null;
        }
    }
  //added by zhangyulin for CR00683126 start
    private void adjustScrollBounds(int y) {
        if (y >= mHeight / 3) {
            mUpperBound = mHeight / 3;
        }
        if (y <= mHeight * 2 / 3) {
            mLowerBound = mHeight * 2 / 3;
        }
    }
    //added by zhangyulin for CR00683126 end
    public void setSimpleListener(SimpleListener l) {
        mSimpleListener = l;
    }

    public interface SimpleListener {
        void drag(int from, int to);

        void drop(int from, int to);

        void remove(int which);

        void visible(int del);
       
        void deleback(int id);
    }
}

猜你喜欢

转载自yulincqupt.iteye.com/blog/1679315