SwipeRefreshLayout与SwipeLayout结合解决冲突

来源:互联网 发布:聚焦网络爬虫 软件 编辑:程序博客网 时间:2024/05/16 09:00
一、前言SwipeRefreshLayout相信大家都有用过,SwipeLayout GitHub地址 是一个侧滑菜单的控件类似QQ聊天列表的效果,而在listview
中这种效果比较多,但是SwipeRefreshLayout与侧滑貌似没有太多,刚好前段时间朋友遇到这个问题,今天有时间便来解决看看。
(刚开始写博客很多不懂希望大家多多包涵)
二、直接上代码
package com.example.administrator.widget.widget;import android.content.Context;import android.support.v4.widget.SwipeRefreshLayout;import android.util.AttributeSet;import android.view.MotionEvent;import android.widget.ListView;import com.daimajia.swipe.SwipeLayout;/** * Created by Administrator on 2017/8/1 */public class MySwipeRefreshLayout extends SwipeRefreshLayout {    private int pressX, pressY;//按下时的X Y坐标    private boolean isIntercept=true;//是否拦截此次事件    private boolean isJustClose =false;//本次按下时是否是关闭swipeLayout    private ListView listView;//绑定的listview    private SwipeLayout swipeLayout;//当前打开的SwipeLayout    public MySwipeRefreshLayout(Context context) {        super(context);    }    public MySwipeRefreshLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN :                pressX = (int) ev.getX();                pressY = (int) ev.getY();                if (swipeLayout!=null ){//如果SwipeLayout不为null说明已经有过打开的SwipeLayout所以就行关闭                    swipeLayout.close();                    isJustClose =true;//本次DOWN事件中关闭了close                }                break;            case MotionEvent.ACTION_MOVE :                if ( ! isIntercept)                    return false ;                if (isJustClose)//本次DOWN事件中关闭了SwipeLayout所以本次不会再走move事件,即不会滑出SwipeLayout                    break ;                double angle= Math.atan((ev.getY()- pressY)/(ev.getX()- pressX));//计算滑动的角度                int degrees= (int) Math.toDegrees(angle);                if (degrees>=-45&&degrees<=45){//如果滑动在45度以内则滑出SwipeLayout                    isIntercept=false;//滑出SwipeLayout后需要进行拦截listview的滑动                    swipeLayout=getChildSwipeLayout();//获得当前滑出的SwipeLayout                    return false;                }else{                    break;                }            case  MotionEvent.ACTION_UP :                isJustClose =false;//将次参数还原为默认值                if (swipeLayout!=null && isIntercept){//SwipeLayout不为null说明有展开的SwipeLayout,并且滑出SwipeLayout的事件已经结束                    if (swipeLayout==getChildSwipeLayout())//如果当前点击的SwipeLayout和展开的是一样的则做默认处理                        swipeLayout.close();                    swipeLayout=null ;                    return true ;                }                isIntercept=true;////将次参数还原为默认值                break;        }        return super.onInterceptTouchEvent(ev);    }    /**     * 绑定对当前的listivew     */    public void setListView(ListView listView){        this.listView=listView;    }    /**     * 获取当前点击位置的子View即SwipeLayout     * @return 当前的SwipeLayout     */    private SwipeLayout getChildSwipeLayout(){        int position=listView.pointToPosition(pressX,pressY);//根据按下的X Y坐标获取position        position=position- listView.getFirstVisiblePosition();//获取当前显示view的下标        return (SwipeLayout) listView.getChildAt(position);//获取当前SwipeLayout    }}
代码注释已经比较详细了,接下来通过每个事件进行下讲解:
首先是按下时的代码
  case MotionEvent.ACTION_DOWN :                pressX = (int) ev.getX();                pressY = (int) ev.getY();                if (swipeLayout!=null ){//如果SwipeLayout不为null说明已经有过打开的SwipeLayout所以就行关闭                    swipeLayout.close();                    isJustClose =true;//本次DOWN事件中关闭了close                }                break;
这里第一次按下时只会执行前面两句后面暂时不会执行因此暂不讲解
接下来是滑动事件
  case MotionEvent.ACTION_MOVE :                if ( ! isIntercept)                    return false ;                if (isJustClose)//本次DOWN事件中关闭了SwipeLayout所以本次不会再走move事件,即不会滑出SwipeLayout                    break ;                double angle= Math.atan((ev.getY()- pressY)/(ev.getX()- pressX));//计算滑动的角度                int degrees= (int) Math.toDegrees(angle);                if (degrees>=-45&&degrees<=45){//如果滑动在45度以内则滑出SwipeLayout                    isIntercept=false;//滑出SwipeLayout后需要进行拦截listview的滑动                    swipeLayout=getChildSwipeLayout();//获得当前滑出的SwipeLayout                    return false;                }else{                    break;                }
这里第一次move时智慧判断角度是否在此范围,如果在此范围可以判定为用户需要滑出侧滑菜单,然后将isIntercept设置为false并且获取swipelayout,当下次move事件触发时isIntercept为false说明侧滑菜单已经滑出所以直接return false 这样不会触发父类也就是SwipeRefreshLayout的事件当然也不会滑动listview 更不会有刷新效果。起到一个拦截listview滑动事件的效果
最后当手指抬起时
case  MotionEvent.ACTION_UP :    isJustClose =false;//将次参数还原为默认值    if (swipeLayout!=null && isIntercept){//SwipeLayout不为null说明有展开的SwipeLayout,并且滑出SwipeLayout的事件已经结束        if (swipeLayout==getChildSwipeLayout())//如果当前点击的SwipeLayout和展开的是一样的则做默认处理            swipeLayout.close();        swipeLayout=null ;        return true ;    }    isIntercept=true;////将次参数还原为默认值    break;

这里第一次抬起其实并不会走判断内的方法,因为isIntercept为false 所以第一次的up事件可以说没实质意义所以不做过多的讲解

当第二次事件发生时分两种情况
1、单纯的点击事件
这时的down事件不仅会获取XY坐标还会进入判断因为在上次move事件中swipeLayout已经有值了所以说明侧滑菜单已经滑出 需要关闭,然后给isJustClose赋值为true,这个在接下来move会用到
case MotionEvent.ACTION_DOWN :    pressX = (int) ev.getX();    pressY = (int) ev.getY();    if (swipeLayout!=null ){//如果SwipeLayout不为null说明已经有过打开的SwipeLayout所以就行关闭        swipeLayout.close();        isJustClose =true;//本次DOWN事件中关闭了close    }    break;
接下来是move事件这时因为刚才的isJustClose为true所以直接跳出move避免滑动时再次触发判定引发错乱所以本次事件其实move事件没有实质意义
case MotionEvent.ACTION_MOVE :    if ( ! isIntercept)        return false ;    if (isJustClose)//本次DOWN事件中关闭了SwipeLayout所以本次不会再走move事件,即不会滑出SwipeLayout        break ;    double angle= Math.atan((ev.getY()- pressY)/(ev.getX()- pressX));//计算滑动的角度    int degrees= (int) Math.toDegrees(angle);    if (degrees>=-45&&degrees<=45){//如果滑动在45度以内则滑出SwipeLayout        isIntercept=false;//滑出SwipeLayout后需要进行拦截listview的滑动        swipeLayout=getChildSwipeLayout();//获得当前滑出的SwipeLayout        return false;    }else{        break;    }
最后是up事件 这时将isJustClose还原为默认的false 然后开始判定swipelayout肯定不为null因为dowm事件都已经判定过了而isIntercept上次up事件已经还原为了true所以本次可以进入判断进入判断后再次判断点击的swipelayout与已经展开的swipelayout是否为同一个若是便关闭,这里有个逻辑是swipelayout控件本身点击自身是可以关闭的,但是由于down事件中的处理并不能关闭,至于具体原因暂时没有研究过尴尬  所以这里需要手动关闭下,关闭后return true拦截所以得事件这样便不会触发onItemClick事件,因为我们的目的此次就是关闭swipelayout而不是点击。
case  MotionEvent.ACTION_UP :    isJustClose =false;//将次参数还原为默认值    if (swipeLayout!=null && isIntercept){//SwipeLayout不为null说明有展开的SwipeLayout,并且滑出SwipeLayout的事件已经结束        if (swipeLayout==getChildSwipeLayout())//如果当前点击的SwipeLayout和展开的是一样的则做默认处理            swipeLayout.close();        swipeLayout=null ;        return true ;    }    isIntercept=true;////将次参数还原为默认值    break;

2、滑动的情况:
这种情况就是按下后关闭了侧滑菜单但是滑动如果又触发了侧滑菜单的判定但是其实侧滑菜单并没有出来,因为SwipeRefreshLayout在你上下滑动的时候已经将事件消费了,所以这时需要在Down中的isJustClose来判断如果此次关闭了侧滑菜单那么move便不会走要下一次即抬起后下一次滑动时才会执行。

三、结语 这里说下这两个控件的结合,这两个控件结合其实很好了已经如果侧滑时其实有一种情况是不会触发listview的滑动的就是在没到顶的时候,当listview滑动时也不会触发侧滑菜单,所以本文只是解决了滑到顶部也就是会触发下拉刷新的的情况。

最后给个demo的地址 我相信可能还有问题希望大家来吐槽本文demo


阅读全文
0 0
原创粉丝点击