首页 > 代码库 > Android 仿iPhone ListView拖动排序 按钮联动删除显示隐藏

Android 仿iPhone ListView拖动排序 按钮联动删除显示隐藏

//需要修改ListView类 重写onInterceptTouchEvent()和onTouchEvent()//试验了另一种方法,改写ListView的每一行中拖曳图标的 onTouchEvent(),但效果不理想。public class MainActivity extends Activity {	DeleteAdapter deleteAdapter;	DragListView listView;	boolean bFlag;	ImageButton button;	@Override	public void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		deleteAdapter = new DeleteAdapter(this, getData());		listView = (DragListView) findViewById(R.id.listView1);		listView.setAdapter(deleteAdapter);		button = (ImageButton) findViewById(R.id.imageButton1);		bFlag = false;		button.setOnClickListener(new OnClickListener() {			@Override			public void onClick(View arg0) {				// TODO Auto-generated method stub				if (!bFlag) {					deleteAdapter.imgVisibility = true;										button.setPressed(true);					bFlag = true;																		deleteAdapter.notifyDataSetChanged();					listView.setSelector(android.R.color.transparent);				} else {					deleteAdapter.imgVisibility = false;					deleteAdapter.imgVisible = new boolean[deleteAdapter							.getCount()];					button.setPressed(false);					bFlag = false;					deleteAdapter.notifyDataSetChanged();					listView.setSelector(android.R.drawable.list_selector_background);				}			}		});		listView.setOnItemClickListener(new OnItemClickListener() {			@Override			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,					long arg3) {				// TODO Auto-generated method stub				if (bFlag) {					if (deleteAdapter.imgDVisible) {						deleteAdapter.imgDVisible = false;						deleteAdapter.imgVisible = new boolean[deleteAdapter.getCount()];						deleteAdapter.notifyDataSetChanged();					}				}			}		});	}	private List<HashMap<String, Object>> getData() {		// 新建一个集合类,用于存放多条数据		ArrayList<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();		HashMap<String, Object> map = null;		for (int i = 1; i <= 100; i++) {			map = new HashMap<String, Object>();			map.put("title", i);			map.put("img", R.drawable.img);			map.put("imgD", R.drawable.imgd);			map.put("imgDrag", R.drawable.imgdrag);			list.add(map);		}		return list;	}	@Override	public boolean onCreateOptionsMenu(Menu menu) {		getMenuInflater().inflate(R.menu.activity_main, menu);		return true;	}}<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <ImageButton        android:id="@+id/imageButton1"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_alignParentTop="true"        android:src="http://www.mamicode.com/@drawable/ic_launcher" />    <com.example.test.DragListView        android:id="@+id/listView1"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:layout_below="@+id/imageButton1"        >    </com.example.test.DragListView></RelativeLayout><?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:orientation="horizontal" >    <ImageView        android:id="@+id/image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="http://www.mamicode.com/@drawable/img"        android:visibility="invisible"         />    <TextView        android:id="@+id/textView1"        android:layout_width="150dp"        android:layout_height="match_parent" />    <ImageView        android:id="@+id/imageDrag"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="http://www.mamicode.com/@drawable/imgdrag"         android:visibility="invisible"         android:focusable="false"/>    <ImageView        android:id="@+id/imageD"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:src="http://www.mamicode.com/@drawable/imgd"        android:visibility="invisible"  /></LinearLayout>public class DeleteAdapter extends BaseAdapter {	List<HashMap<String, Object>> text;	Context context;	private LayoutInflater mInflater;	boolean imgVisibility = false;	boolean imgVisible[] ;//记录删除按钮可见位置的标记数组  	boolean imgDVisible = false;	public DeleteAdapter(Context context, List<HashMap<String, Object>> text) {		this.text = text;		this.mInflater = LayoutInflater.from(context);		imgVisible = new boolean[text.size()];	}	@Override	public int getCount() {		// TODO Auto-generated method stub		return text.size();	}	@Override	public Object getItem(int arg0) {		// TODO Auto-generated method stub		return text.get(arg0);	}	@Override	public long getItemId(int arg0) {		// TODO Auto-generated method stub		return 0;	}	public void remove(Object object) {		text.remove(object);		notifyDataSetChanged();	}	@SuppressWarnings("unchecked")	public void insert(Object object, int i) {		text.add(i, (HashMap<String, Object>) object);		notifyDataSetChanged();	}	@Override	public View getView(final int arg0, View arg1, ViewGroup arg2) {		// TODO Auto-generated method stub		arg1 = mInflater.inflate(R.layout.listview_item, null);		TextView textView = (TextView) arg1.findViewById(R.id.textView1);		textView.setText(text.get(arg0).get("title").toString());		final ImageView img = (ImageView) arg1.findViewById(R.id.image);		img.setBackgroundResource((Integer) text.get(arg0).get("img"));		final ImageView imgD = (ImageView) arg1.findViewById(R.id.imageD);		imgD.setBackgroundResource((Integer) text.get(arg0).get("imgD"));		final ImageView imgDrag = (ImageView) arg1.findViewById(R.id.imageDrag);		imgDrag.setBackgroundResource((Integer) text.get(arg0).get("imgDrag"));		if (imgVisibility) {			img.setVisibility(View.VISIBLE);			imgDrag.setVisibility(View.VISIBLE);						}							if (imgVisibility && !imgDVisible ) {			img.setVisibility(View.VISIBLE);			imgD.setVisibility(View.INVISIBLE);			imgDrag.setVisibility(View.VISIBLE);			img.setClickable(true);			img.setFocusable(true);		}				if (imgVisibility && imgDVisible && imgVisible[arg0]){			img.setVisibility(View.INVISIBLE);			imgD.setVisibility(View.VISIBLE);		}		img.setOnClickListener(new OnClickListener() {			@Override			public void onClick(View v) {				// TODO Auto-generated method stub//				imgD.setVisibility(View.VISIBLE);//				img.setVisibility(View.INVISIBLE);				imgVisible[arg0] = true;				imgDVisible = true;					notifyDataSetChanged();										}		});				imgD.setOnClickListener(new OnClickListener() {			@Override			public void onClick(View v) {				// TODO Auto-generated method stub				text.remove(arg0);								imgDVisible = false;								imgVisible[arg0] = false;				notifyDataSetChanged();			}		});		if (imgVisibility && imgDVisible ) {			img.setClickable(false);			img.setFocusable(false);		}			return arg1;	}}//设置了  setClickable(false); //但是,按钮仍然会相应点击事件。后来发现setOnClickListener//里的一段代码 if (!isClickable()) { setClickable(true); } //这导致了setOnClickListener之前的setClickable(false)//方法没有起作用。//Button.setClickable() 要在Button.setOnClickListener()后设置,否则不管setClickable的值为//否,都为truepublic class DragListView extends ListView {	private ImageView dragImageView;// 被拖拽项的影像,其实就是一个ImageView	private int dragSrcPosition;// 手指拖动项原始在列表中的位置	private int dragPosition;// 手指拖动的时候,当前拖动项在列表中的位置	private int dragPoint;// 在当前数据项中的位置	private int dragOffset;// 当前视图和屏幕的距离(这里只使用了y方向上)	private WindowManager windowManager;// windows窗口控制类	private WindowManager.LayoutParams windowParams;// 用于控制拖拽项的显示的参数	private int scaledTouchSlop;// 判断滑动的一个距离	private int upScrollBounce;// 拖动的时候,开始向上滚动的边界	private int downScrollBounce;// 拖动的时候,开始向下滚动的边界	public DragListView(Context context, AttributeSet attrs) {		super(context, attrs);		// TODO Auto-generated constructor stub		scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();	}	@Override	public boolean onInterceptTouchEvent(MotionEvent ev) {		// 捕获down事件		if (ev.getAction() == MotionEvent.ACTION_DOWN) {			int x = (int) ev.getX();			int y = (int) ev.getY();			// 选中的数据项位置,使用ListView自带的pointToPosition(x, y)方法			dragSrcPosition = dragPosition = pointToPosition(x, y);			// 如果是无效位置(超出边界,分割线等位置),返回			if (dragPosition == AdapterView.INVALID_POSITION) {				return super.onInterceptTouchEvent(ev);			}			// 获取选中项View			// getChildAt(int position)显示display在界面的position位置的View			// getFirstVisiblePosition()返回第一个display在界面的view在adapter的位置position,可能是0,也可能是4			ViewGroup itemView = (ViewGroup) getChildAt(dragPosition					- getFirstVisiblePosition());			// dragPoint点击位置在点击View内的相对位置			// dragOffset屏幕位置和当前ListView位置的偏移量,这里只用到y坐标上的值			// 这两个参数用于后面拖动的开始位置和移动位置的计算			dragPoint = y - itemView.getTop();			dragOffset = (int) (ev.getRawY() - y);			// 获取右边的拖动图标,这个对后面分组拖拽有妙用			View dragger = itemView.findViewById(R.id.imageDrag);			DeleteAdapter deleteAdapter = (DeleteAdapter) getAdapter();			// 如果在右边位置(拖拽图片左边的20px的右边区域)			if (dragger != null && x > dragger.getLeft() 					&& x < dragger.getRight() 					&& !deleteAdapter.imgDVisible) {				// 准备拖动				// 初始化拖动时滚动变量				// scaledTouchSlop定义了拖动的偏差位(一般+-10)				// upScrollBounce当在屏幕的上部(上面1/3区域)或者更上的区域,执行拖动的边界,downScrollBounce同理定义				upScrollBounce = Math.min(y - scaledTouchSlop, getHeight() / 3);				downScrollBounce = Math.max(y + scaledTouchSlop,						getHeight() * 2 / 3);				// 设置Drawingcache为true,获得选中项的影像bm,就是后面我们拖动的哪个头像				itemView.setDrawingCacheEnabled(true);				Bitmap bm = Bitmap.createBitmap(itemView.getDrawingCache());				// 准备拖动影像(把影像加入到当前窗口,并没有拖动,拖动操作我们放在onTouchEvent()的move中执行)				startDrag(bm, y);			}			return false;		}		return super.onInterceptTouchEvent(ev);	}	public void startDrag(Bitmap bm, int y) {		// 释放影像,在准备影像的时候,防止影像没释放,每次都执行一下		stopDrag();		windowParams = new WindowManager.LayoutParams();		// 从上到下计算y方向上的相对位置,		windowParams.gravity = Gravity.TOP;		windowParams.x = 0;		windowParams.y = y - dragPoint + dragOffset;		windowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;		windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;		// 下面这些参数能够帮助准确定位到选中项点击位置,照抄即可		windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE				| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE				| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON				| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;		windowParams.format = PixelFormat.TRANSLUCENT;		windowParams.windowAnimations = 0;		// 把影像ImagView添加到当前视图中		ImageView imageView = new ImageView(getContext());		imageView.setImageBitmap(bm);		windowManager = (WindowManager) getContext().getSystemService("window");		windowManager.addView(imageView, windowParams);		// 把影像ImageView引用到变量drawImageView,用于后续操作(拖动,释放等等)		dragImageView = imageView;	}	public void stopDrag() {		if (dragImageView != null) {			windowManager.removeView(dragImageView);			dragImageView = null;		}	}	@Override	public boolean onTouchEvent(MotionEvent ev) {		// 如果dragmageView为空,说明拦截事件中已经判定仅仅是点击,不是拖动,返回		// 如果点击的是无效位置,返回,需要重新判断		if (dragImageView != null && dragPosition != INVALID_POSITION) {			int action = ev.getAction();			switch (action) {			case MotionEvent.ACTION_UP:				int upY = (int) ev.getY();				// 释放拖动影像				stopDrag();				// 放下后,判断位置,实现相应的位置删除和插入				onDrop(upY);				break;			case MotionEvent.ACTION_MOVE:				int moveY = (int) ev.getY();				// 拖动影像				onDrag(moveY);				break;			default:				break;			}			return true;		}		// 这个返回值能够实现selected的选中效果,如果返回true则无选中效果		return super.onTouchEvent(ev);	}	public void onDrag(int y) {		if (dragImageView != null) {			windowParams.alpha = 0.8f;			windowParams.y = y - dragPoint + dragOffset;			windowManager.updateViewLayout(dragImageView, windowParams);		}		// 为了避免滑动到分割线的时候,返回-1的问题		int tempPosition = pointToPosition(0, y);		if (tempPosition != INVALID_POSITION) {			dragPosition = tempPosition;		}		// 滚动		int scrollHeight = 0;		if (y < upScrollBounce) {			scrollHeight = 8;// 定义向上滚动8个像素,如果可以向上滚动的话		} else if (y > downScrollBounce) {			scrollHeight = -8;// 定义向下滚动8个像素,,如果可以向上滚动的话		}		if (scrollHeight != 0) {			// 真正滚动的方法setSelectionFromTop()			setSelectionFromTop(dragPosition,					getChildAt(dragPosition - getFirstVisiblePosition())							.getTop() + scrollHeight);		}	}		public void onDrop(int y){	     	    //获取放下位置在数据集合中position	    //定义临时位置变量为了避免滑动到分割线的时候,返回-1的问题,如果为-1,则不修改dragPosition的值,急需执行,达到跳过无效位置的效果	    int tempPosition = pointToPosition(0, y);	    if(tempPosition!=INVALID_POSITION){	        dragPosition = tempPosition;	    }	     	    //超出边界处理	    if(y<getChildAt(0).getTop()){	        //超出上边界,设为最小值位置0	        dragPosition = 0;	    }else if(y>getChildAt(getChildCount()-1).getBottom()){	        //超出下边界,设为最大值位置,注意哦,如果大于可视界面中最大的View的底部则是越下界,所以判断中用getChildCount()方法	        //但是最后一项在数据集合中的position是getAdapter().getCount()-1,这点要区分清除	        dragPosition = getAdapter().getCount()-1;	    }	     	    //数据更新	    if(dragPosition>0&&dragPosition<getAdapter().getCount()){	        	        DeleteAdapter adapter = (DeleteAdapter)getAdapter();	        Object dragItem = adapter.getItem(dragSrcPosition);	        //删除原位置数据项	        adapter.remove(dragItem);	        //在新位置插入拖动项	        adapter.insert(dragItem, dragPosition);	    }	}}

 

Android 仿iPhone ListView拖动排序 按钮联动删除显示隐藏