可以拖动的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);
}
}