最近项目组中要出线下版产品,其中一个界面需要实现一个右滑Listview中item,然后可以删除和重命名该item。正好我最近在看自定义控件,所以自荐做这个页面的交互设计,也算练手。刚开始我想的太简单了,我以为添加一个滑动的action,然后item去响应这个action就好了,至于滑动多少距离,或者说item滚动多少距离,不同的滚动会有怎样的效果,好多实际的问题没有考虑进去,当初自己写出来,也是各种crash。所以上网去看别人写的,后来看了一个,模仿写了一个只能左滑,但是项目需求右滑,我就觉得这简单嘛,结果反过来后滑是滑了,item设置的一些控件没有显示出来,也是醉。最终找到一个比较合适的,然后根据那个自己重写了一下ListView,和一个适配器Adapter。
首先写一个类继承ListView,我定义为CustomListView:
public class CustomListView extends ListView {
/**禁止侧滑模式*/
public static int MOD_FORBID = 0;
/**从左向右滑出菜单模式*/
public static int MOD_LEFT = 1;
/**当前的模式*/
private int mode = MOD_FORBID;
/**左侧菜单的长度*/
private int leftLength = 0;
/**
* 当前滑动的ListView position
*/
private int slidePosition;
/**
* 手指按下X的坐标
*/
private int downX;
/**
* 手指按下Y的坐标
*/
private int downY;
/**
* ListView的item
*/
private View itemView;
/**
* 滑动类
*/
private Scroller scroller;
/**
* 认为是用户滑动的最小距离
*/
private int mTouchSlop;
/**
* 判断是否可以侧向滑动
*/
private boolean canMove = false;
/**
* 标示是否完成侧滑
*/
private boolean isSlided = false;
public CustomListView(Context context) {
this(context,null);
}
public CustomListView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public CustomListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
scroller = new Scroller(context);
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
//初始化菜单的划出模式,供外部调用
public void initSlideMode(int mode){
this.mode = mode;
}
/**
* 处理我们拖动ListView item的逻辑
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
int lastX = (int) ev.getX();
switch (action) {
case MotionEvent.ACTION_DOWN:
/*当前模式不允许滑动,则直接返回,交给ListView自身去处理*/
if(this.mode == MOD_FORBID){
return super.onTouchEvent(ev);
}
// 如果处于侧滑完成状态,侧滑回去,并直接返回
if (isSlided) {
scrollBack();
return false;
}
// 假如scroller滚动还没有结束,我们直接返回
if (!scroller.isFinished()) {
return false;
}
downX = (int) ev.getX();
downY = (int) ev.getY();
slidePosition = pointToPosition(downX, downY);
// 无效的position, 不做任何处理
if (slidePosition == AdapterView.INVALID_POSITION) {
return super.onTouchEvent(ev);
}
// 获取我们点击的item view
itemView = getChildAt(slidePosition - getFirstVisiblePosition());
/*此处根据设置的滑动模式,自动获取左侧菜单的长度*/
if(this.mode == MOD_LEFT){
this.leftLength = -itemView.getPaddingLeft();
}
break;
case MotionEvent.ACTION_MOVE:
if (!canMove
&& slidePosition != AdapterView.INVALID_POSI