swipmenulistview+pulltorefresh整合

大概在今年1月份吧,项目中有需要用到pulltorefresh+swipmenulistview,但是这两个控件整合到一块,在网上找了好久都没找到好的,要么是整合的不好,要么是直接重写swipmenulistview控件来实现下拉刷新的功能


于是我就把两个控件整合到了一起,以后项目想用的时候就很方便了哈~ 先看看如下效果


是不是很爽?!接下来我就分析其中的原理,细节性的我就不说,我就大概给个思路和一些关键性代码,细节性的大家就去下源码看看吧~


先分析下,上拉和下拉操作都要给pulltorefresh处理,左滑和右滑都要交给swipmenulistview,然后swipmenulistview的父布局是pulltorefresh,刚开始整合的时候很容易,功能也能实现,但是用户体验非常差,例如swipmenulistview左滑和右滑时,如果滑动时,Y轴方向的移动距离达到触发下拉事件的话,左右滑动就会停止,滑动事件被pulltorefresh进行处理,导致左右滑动就无法进行了 

既然原因知道了,然后需要根据Touch事件的分发处理机制,那问题很容易解决,在swipmenulistview进行滑动时,所有的滑动事件都交由swipmenulistview处理就行,但是根据Touch事件的触发机制,是从外到内,即父布局传到子布局,这里的父布局就是pulltorefresh,子布局就是swipmenulistview。 一旦swipmenulistview进行滑动了,那么在swipmenulistview滑动事件未处理完毕之前,所有的Touch事件都交由swipmenulistview进行处理,思路就是这样子 接下来看一些修改的关键性代码


首先swipmenulistview需要暴露一个接口,来让父布局即pulltorefresh监听它的当前状态,pulltorefresh根据swipmenulistview状态是否将Touch事件传递下去

在SwipeMenuListView这个类中,有这么个属性

private int mTouchPosition;
它就是代表着当前swipmenulistview的状态,下面这三个属性,分别代表当前swipmenulistview的状态,TOUCH_STATE_X代表现在是左右滑动中,在这个状态中,所有的Touch事件需要它处理,父布局不能处理

private static final int TOUCH_STATE_NONE = 0;
private static final int TOUCH_STATE_X = 1;
private static final int TOUCH_STATE_Y = 2;


现在 就是关键的部分,就是在SwipeMenuListView进行滑动时,实时改写mTouchPosition的状态,然后父布局根据这个状态是否需要处理当前的Touch事件

首先如何动态改写:覆写SwipeMenuListView的onTouchEvent(MotionEvent ev),如下代码

public boolean onTouchEvent(MotionEvent ev) {
        int action = MotionEventCompat.getActionMasked(ev);
        action = ev.getAction();
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mDownX = ev.getX();
                mDownY = ev.getY();
                mTouchState = TOUCH_STATE_NONE;//重置当前状态

                if (mTouchView != null && mTouchView.isOpen()) {
                    mTouchView.smoothCloseMenu();
                    return false;
                }
                mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
                View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
                if (view instanceof SwipeMenuLayout) {
                    mTouchView = (SwipeMenuLayout) view;
                    mTouchView.setmSwipeStateListen(new SwipeMenuLayout.SwipeStateListen() {
                        @Override
                        public void stateChange() {
                            mTouchState = TOUCH_STATE_NONE;
                        }
                    });
                }
                if (mTouchView != null) {
                    mTouchView.onSwipe(ev);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                float dy = Math.abs((ev.getY() - mDownY));
                float dx = Math.abs((ev.getX() - mDownX));
                if (mTouchState == TOUCH_STATE_X) {
                    // 滑动
                    if (mTouchView != null) {
                        mTouchView.onSwipe(ev);
                    }
                    getSelector().setState(new int[]{0});
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                } else {
                    // Log.i("byz", "state = " + mTouchState + ", dx = " + dx
                    // + ", max = " + MAX_X);
                    if (mTouchState != TOUCH_STATE_X && Math.abs(dy) > MAX_Y) {//是左右滑动,改写状态为TOUCH_STATE_X
                        mTouchState = TOUCH_STATE_Y;
                    }
                    if (mTouchState != TOUCH_STATE_Y && dx > MAX_X) {//是左右滑动,改写状态为TOUCH_STATE_Y
                        mTouchState = TOUCH_STATE_X;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mTouchState == TOUCH_STATE_X) {//将滑动动画播放完毕
                    if (mTouchView != null) {
                        mTouchView.onSwipe(ev);
                    }
                    ev.setAction(MotionEvent.ACTION_CANCEL);
                    super.onTouchEvent(ev);
                    return true;
                }
                break;
        }
        return super.onTouchEvent(ev);
    }


状态已经实时改写,现在就是在pulltorefresh的onInterceptTouchEvent(MotionEvent event)方法中进行事件的分发操作,pulltorefresh根据状态为1的就进行事件下发,自己不处理,如下代码

 @Override
    public final boolean onInterceptTouchEvent(MotionEvent event) {
        if (mListView.getmTouchState() == 1) {
            return false;
        }
        return super.onInterceptTouchEvent(event);
    }

pulltorefresh这个控件相信在很多项目都有使用过,即防ios的下拉刷新效果~下载地址 


swipmenulistview 这个控件也是仿ios的item的左滑效果,以有更多功能选项 下载地址


整合swipmenulistview+pulltorefresh 点击打开链接,如果打不开,可以私信我~(项目是用Gradle构建,最好用as打开)



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值