解决SlidingMenu与ViewPager的滑动冲突尝试

来源:互联网 发布:java工程师考什么证 编辑:程序博客网 时间:2024/05/22 15:24

模仿唯品会侧边栏与viewpager场景,尝试解决SlidingMenu与ViewPager的滑动冲突。

SlidingMenu使用张鸿洋大神的自定义控件。
参考:http://blog.csdn.net/lmj623565791/article/details/39257409

效果如下:

这里写图片描述

代码讲解:

采用内部拦截法,slidingmenu先不拦截事件,让事件传到viewpager。

        @Override        public boolean onInterceptHoverEvent(MotionEvent event)              {        int action = event.getAction();        if(action == MotionEvent.ACTION_DOWN){            return false;        }else{            return true;        }    }

如果只看上面的代码的话,只有ACTION_DOWN事件传递到子view,但是子view可以通过设置requestDisallowInterceptTouchEvent(true);阻止父层拦截事件,后面也可以看到子view在ACTION_DOWN时设置该方法为true,所以尽管父层是想拦截除DOWN之外的其它事件,也没办法吧。

viewpager获得事件,在对事件分发时对滑动进行判断,当为第0个界面并且依然向右滑动时,将事件交还给slidingmenu。

 @Override    public boolean dispatchTouchEvent(MotionEvent ev) {        int x = (int) ev.getX();        int y = (int) ev.getY();        switch (ev.getAction()){            case MotionEvent.ACTION_DOWN:                getParent().requestDisallowInterceptTouchEvent(true);                break;            case MotionEvent.ACTION_MOVE:                if(!scrollable){                    getParent().requestDisallowInterceptTouchEvent(false);                    break;                }                int deltaX = x - mLastX;                if( getCurrentItem()==0 && deltaX >0 ){                    getParent().requestDisallowInterceptTouchEvent(false);                }                break;            case MotionEvent.ACTION_UP:                break;        }        mLastX = x;        mLastY = y;        return super.dispatchTouchEvent(ev);    }

其中有个布尔值scrollable,当slidingmenu打开时,scrollable设为false,此时viewpager一定会把所有的事件交给slidingmenu。即通过scrollable控制是否阻止父层拦截事件,从而决定事件是被slidingMenu拦截还是传到viewpager。

case MotionEvent.ACTION_MOVE:     if(!scrollable){                          getParent().requestDisallowInterceptTouchEvent(false);        break;     }

而当slidingmenu关闭时,再把scrollable设为true,则一切又回到最初的样子,形成一个循环,问题是viewpager并不知道slidingmenu什么时候关闭,slidingmenu也不能设置viewpager的属性,所有只能交给于两者都有关联的activity处理,让activity监听slidingmenu的打开和关闭,然后设置viewpager的scrollable。

public interface SlidingMenuListener {    void open();    void close();}// 在activity中监听slidingMenu的打开和关闭操作slidingMenu.setSlidingMenuListener(new SlidingMenuListener() {            @Override            public void open() {                viewPager.setScrollable(false);            }            @Override            public void close() {                viewPager.setScrollable(true);            }        });

slidingmenu在滑动的实现中回调:

@Override    public boolean onTouchEvent(MotionEvent ev)    {        int action = ev.getAction();        switch (action)        {        // Up时,进行判断,如果显示区域大于菜单宽度一半则完全显示,否则隐藏            case MotionEvent.ACTION_UP:                int scrollX = getScrollX();                if (scrollX > mHalfMenuWidth)                {                    this.smoothScrollTo(mMenuWidth, 0);                    isOpen = false;                    Logger.i("关闭");                    listener.close();                } else                {                    this.smoothScrollTo(0, 0);                    isOpen = true;                    Logger.i("打开");                    listener.open();                }                return true;        }        return super.onTouchEvent(ev);    }

感觉像是一个简单的有限状态机,总是可以在一个循环中回到原点。

源码链接:解决SlidingMenu和ViewPager的滑动冲突

0 5