swipmenulistview+pulltorefresh整合

来源:互联网 发布:最新网络币 编辑:程序博客网 时间:2024/06/07 01:27

大概在今年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打开)



0 0
原创粉丝点击