• 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="@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="@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="@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="@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的值为//否,都为true
    
    
    
    public 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);
    	    }
    	}
    }
    
  • 相关阅读:
    C++面向对象高级编程(下)第二周-Geekband
    C++面向对象高级编程(下)第一周-Geekband
    C++面向对象高级编程(下)-Geekband
    堆,栈,内存管理, 拓展补充-Geekband
    C++面向对象高级编程(上)-Geekband
    MFC 多屏显示
    Open CASCADE Technology: IGES Support
    JAVA反射
    HashMap
    Linux 系统编程
  • 原文地址:https://www.cnblogs.com/luscinia/p/4177900.html
Copyright © 2020-2023  润新知