android listview滑动删除,实现item的点击缩回

  最近有一个滑动删除列表的需求,本来以为很简单的,做的和QQ的一样就好,结果自己写发现不是这么回事,QQ的滑动删除是滑动就打开,再触碰除了打开的区域以外的区域,打开的item就回缩,其实就是状态的判断,但是我的判断似乎总是出问题,于是用了点小技巧,现在的功能是实现了,滑动打开,点击其他地方就回缩,特此记录。


其实主要还是滑动事件的分发和item状态的判断,我这里参考了http://blog.csdn.net/harvic880925/article/details/45317951http://blog.csdn.net/harvic880925/article/details/45317951这篇博客,把自定义listview改成自定义linearlayout,由layout自己实现回滚,这样就只需要处理好打开关闭状态就行了,下面看代码

/**
 * 滑动的监听,传递当前滑动的layout和状态(打开或者关闭),用于action_up
 */
public static interface OnScrollListener {
    public void onScroll(DeleteLinearLayout view,int state);
}

public void setOnScrollListenre(OnScrollListener onScrollListener) {
    this.onScrollListener = onScrollListener;
}

/**
 * 触碰的监听,传递当前触碰的layout,用于action_down
 */
public static interface OnTouchListener {
    public void onTouch(DeleteLinearLayout view);
}

public void setOnTouchListener(OnTouchListener onTouchListener) {
    this.onTouchListener = onTouchListener;
}

public DeleteLinearLayout(Context context) {
    this(context, null);
}

public DeleteLinearLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public DeleteLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
}

private void init(Context context) {
    this.context = context;
    mScroller = new Scroller(context, new LinearInterpolator(context, null));
    touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    int maxLength = 300;
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            xDistance = yDistance = 0f;
            xLast = ev.getX();
            yLast = ev.getY();
            currentX = (int) ev.getX();
            mlastX = (int) ev.getX();
            xDistance = yDistance = 0f;
            xLast = ev.getX();
            yLast = ev.getY();
            onTouchListener.onTouch(this);
        }
        break;
        case MotionEvent.ACTION_MOVE: {
            //如果当前状态是关闭状态才执行,相当于拦截了打开状态的action_move
            if(!Utils.getSP(context)) {
                final float curX = ev.getX();
                final float curY = ev.getY();

                // 计算在X和Y方向的偏移量
                xDistance += Math.abs(curX - xLast);
                yDistance += Math.abs(curY - yLast);
                xLast = curX;
                yLast = curY;
                // 横向距离大于纵向距离,layout才可以滑动
                if (xDistance > yDistance && xDistance >touchSlop) {
                    currentX = (int) ev.getX();
                    int scrollX = getScrollX();
                    int reallyX = scrollX + mlastX - currentX;
                    if (reallyX < 0) {
                        reallyX = 0;
                    } else if (reallyX > maxLength) {
                        reallyX = maxLength;
                    }
                    this.scrollTo(reallyX, 0);
                    mlastX = currentX;
                }
            }
        }
        break;
        case MotionEvent.ACTION_UP: {
            //无论是否拦截action_move,都会进来这一步,所以如果拦截了action_move,reallyX 为0,把当前状态设为了关闭
            int scrollX = this.getScrollX();
            int reallyX = scrollX + mlastX - currentX;
            if (scrollX > maxLength / 2) {
                reallyX = maxLength;
                CURRENT_STATE = STATE_OPEN;
                //保存listview当前的状态为打开
                Utils.setSP(context,true);
            } else {
                CURRENT_STATE = STATE_CLOSE;
                //保存listview当前的状态为关闭
                Utils.setSP(context,false);
                reallyX = 0;
            }
            onScrollListener.onScroll(this,CURRENT_STATE);
            mScroller.startScroll(scrollX, 0, reallyX - scrollX, 0);
            invalidate();
        }
        break;
    }
    return super.onTouchEvent(ev);
}

@Override
public void computeScroll() {
    super.computeScroll();
    if (mScroller.computeScrollOffset()) {
        this.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
    }
    invalidate();
}

//提供给外面调用的方法,用于使layout滚回原点
public void smoothScrollTo(int x, int y) {
    int scrollX = getScrollX();
    int deltaX = x - scrollX;
    mScroller.startScroll(scrollX, 0, deltaX, 0);
    invalidate();
}

然后是MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (MyListView) findViewById(R.id.listview);
    for (int i = 0; i < 200; i++) {
        MyAdapter.Data data = new MyAdapter.Data();
        data.title = (i + "个人");
        list.add(data);
    }
    adapter = new MyAdapter(this, list, new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(v.getId() == R.id.del) {
                int positon = listView.getPositionForView(v);
                Utils.setSP(MainActivity.this,false);
                adapter.removeItem(positon);
                curState = 2;
                adapter.notifyDataSetChanged();
            }
        }
    }, new DeleteLinearLayout.OnScrollListener() {
        @Override
        public void onScroll(DeleteLinearLayout view, int state) {
            if (state == 1) {
                lastLayout = view;
            }
            curState = state;
        }
    }, new DeleteLinearLayout.OnTouchListener() {
        @Override
        public void onTouch(DeleteLinearLayout view) {
            if (curState == 1) {
                lastLayout.smoothScrollTo(0, 0);
            }
        }
    });
    listView.setAdapter(adapter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    Utils.setSP(this,false);

自定义的listview,不处理具体事件
public boolean onTouchEvent(MotionEvent event) {
    int maxLength = 300;

    int currentY = (int) event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            currentX = (int) event.getX();
            //我们想知道当前点击了哪一行
            int position = pointToPosition(currentX, currentY);
            if (position != INVALID_POSITION) {
                MyAdapter.Data data = (MyAdapter.Data) getItemAtPosition(position);
                itemLayout = data.listLayout;
                Log.e("Listview action down: ","valid positon");
            } else {
                Log.e("Listview action down: ","invalid positon");

            }
        }

        case MotionEvent.ACTION_MOVE:
            final float curX = event.getX();
            final float curY = event.getY();

            // 计算在X和Y方向的偏移量
            xDistance += Math.abs(curX - xLast);
            yDistance += Math.abs(curY - yLast);
            xLast = curX;
            yLast = curY;
            break;
    }
    if (itemLayout != null) {
        itemLayout.onTouchEvent(event);
    } else {
    }
    if (xDistance > yDistance) {
        return true;
    }
    return super.onTouchEvent(event);

}


@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
            xDistance = yDistance = 0f;
            xLast = ev.getX();
            yLast = ev.getY();

            break;
        default:
            break;
    }
    return super.dispatchTouchEvent(ev);
}
这里用了个小技巧,就是用sharepreferences保存了linearlayout的当前状态,第一次点击,
Utils.getSP()返回false,因此可以滑动,走到action_up,如果最后状态为打开,则将
sharepreferences设置为true,那么第二次点击的时候,就不会进去action_move,故不会滑动,但是还会进入action_up,最后状态由于action_move的时候没有滑动,为关闭状态,因此把shareprefer置为false,一直循环。

主要是正规的方法想不出来。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值