功能描述:可在ListView中,让某一项跟随便手指滑动而左右移动,并产生透明度变化,手指松开时,根据移动距离大小,判断是否要删除该项。
方法:
一、自定义adapter,在getView()方法中,对列表项绑定OnTouchListener,以确定所选择的是哪一项。(在该监听器中,只能响应ACTION_DOWN事件)
1 public class ListAdapter extends BaseAdapter { 2 3 private Context context; 4 private List<String> list; 5 6 private View selectedView; 7 private int selectedItem; 8 9 public View getSelectedView(){ 10 return selectedView; 11 } 12 13 public void delete(){ 14 //删除所选的项 15 list.remove(selectedItem); 16 notifyDataSetChanged(); 17 selectedView=null; 18 } 19 20 public void cancel(){ 21 //取消操作,还原被移动项的位置和透明度 22 ObjectAnimator.ofFloat(selectedView, "x", 0f).start(); 23 ObjectAnimator.ofFloat(selectedView, "alpha", 1.0f).start(); 24 selectedView=null; 25 } 26 27 public ListAdapter(Context context, List<String> list) { 28 super(); 29 this.context = context; 30 this.list = list; 31 } 32 33 @Override 34 public int getCount() { 35 // TODO Auto-generated method stub 36 return list.size(); 37 } 38 39 @Override 40 public Object getItem(int arg0) { 41 // TODO Auto-generated method stub 42 return list.get(arg0); 43 } 44 45 @Override 46 public long getItemId(int position) { 47 // TODO Auto-generated method stub 48 return position; 49 } 50 51 @Override 52 public View getView(final int position, View convertView, ViewGroup parent) { 53 // TODO Auto-generated method stub 54 55 View view = LayoutInflater.from(context).inflate(R.layout.list_item, 56 null); 57 TextView textView = (TextView) view.findViewById(R.id.textView); 58 textView.setText(list.get(position)); 59 60 view.setOnTouchListener(new OnTouchListener() { 61 62 @Override 63 public boolean onTouch(View v, MotionEvent event) { 64 // TODO Auto-generated method stub 65 switch(event.getAction()){ 66 case MotionEvent.ACTION_DOWN: 67 selectedView=v; 68 selectedItem=position; 69 break; 70 } 71 return false; 72 } 73 }); 74 75 return view; 76 } 77 78 }
二、为ListView绑定OnTouchListener,对各种事件做相应处理。
1 public class MainActivity extends Activity { 2 3 private ListView listView; 4 private ListAdapter adapter; 5 private List<String> list; 6 7 @Override 8 protected void onCreate(Bundle savedInstanceState) { 9 super.onCreate(savedInstanceState); 10 setContentView(R.layout.activity_main); 11 12 listView = (ListView) findViewById(R.id.listView); 13 14 list = new ArrayList<String>(); 15 for (int i = 0; i < 20; i++) { 16 list.add(i + "-----------" + i); 17 } 18 19 adapter = new ListAdapter(this, list); 20 listView.setAdapter(adapter); 21 22 listView.setOnTouchListener(new OnTouchListener() { 23 24 private View selectedView; 25 private float oldX; 26 private float oldY; 27 28 @Override 29 public boolean onTouch(View v, MotionEvent event) { 30 // TODO Auto-generated method stub 31 if (adapter.getSelectedView() == null) { 32 return false; 33 } 34 35 switch (event.getAction()) { 36 case MotionEvent.ACTION_DOWN: 37 // 按下事件,获取用户要操作的项,和事件坐标 38 selectedView = adapter.getSelectedView(); 39 oldX = event.getX(); 40 oldY = event.getY(); 41 42 break; 43 case MotionEvent.ACTION_MOVE: 44 /* 45 * 移动事件,若y方向移动距离大于x方向移动距离, 46 * 则认为用户是想上下滚动列表。 47 * 否则,用户是想滑动列表的某一项。 48 */ 49 float distanceX=event.getX()-oldX; 50 float distanceY=event.getY()-oldY; 51 if(Math.abs(distanceX)>Math.abs(distanceY)){ 52 selectedView.setX(selectedView.getX()+distanceX); 53 selectedView.setAlpha(Math.max(0.1f,1-Math.abs(selectedView.getX()/200))); 54 } 55 oldX=event.getX(); 56 oldY=event.getY(); 57 break; 58 case MotionEvent.ACTION_UP: 59 /* 60 * 弹起事件,根据x方向移动距离的大小, 61 * 判断要进行什么操作 62 */ 63 if(Math.abs(selectedView.getX())>200){ 64 //移动距离大于200px,则删除该项 65 //(直接删除会有点突兀,可增加确认对话框或删除动画等。) 66 adapter.delete(); 67 }else{ 68 //否则,将其还原 69 adapter.cancel(); 70 } 71 72 break; 73 74 } 75 return false; 76 } 77 }); 78 79 } 80 81 }
整体流程为:
1.用户手指触摸屏幕,adapter中的某一列表项响应ACTION_DOWN事件,设置所选项即selectedView和selectedItem的值。
2.ListView响应ACTION_DOWN事件,获取所选项selectedView。
3.用户移动手指,ListView响应ACTION_MOVE事件,根据x方向和y方向距离大小判断是否要滑动列表项。若是,则根据x方向距离设置selectedView的坐标和透明度。
4.用户手指离开屏幕,根据移动距离判断是否要删除该项。