悬浮导航栏StickyNavLayout的实现--如何实现滑动不
2016-05-27 本文已影响1452人
皮球二二
致敬鸿洋,这篇文章是基于他的项目改造而成的
本次主题将分成3个部分进行讲解,前2部分基本上是对鸿洋的代码解读以及一些小bug的处理,第三部分是针对鸿洋Android-StickyNavLayout不支持的功能进行优化处理。本文对应的项目地址在Github
对上篇文章还有印象的同学,你们肯定会有一个问题:我可不可以每次不要停顿,直接向下滑动或者向上滑动?现在,我就告诉你如何去实现。
我们知道dispatchTouchEvent是用来进行事件分发的,他说发down,那边该层的onInterceptTouchEvent就乖乖的发down,说发move,那边就跟着发move。诸位是不是有想法了!!!
来一段代码
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
int y= (int) ev.getY();
if (ev.getAction()==MotionEvent.ACTION_MOVE) {
View view=id_bottomview.getChildAt(id_bottomview.getFirstVisiblePosition());
if (!isInControl && isTopHidden && (y-lastY)>0 && view!=null && view.getTop()==0) {
isInControl=true;
ev.setAction(MotionEvent.ACTION_CANCEL);
MotionEvent event=ev.obtain(ev);
dispatchTouchEvent(ev);
event.setAction(MotionEvent.ACTION_DOWN);
return dispatchTouchEvent(event);
}
}
return super.dispatchTouchEvent(ev);
}
这段代码的目的是,当我们下拉滑动到蓝色区域临界点的时候,直接将当前的move事件终止,转成Cancel事件并且发出一个Down事件重新玩。这边有一个标志位isInControl
很重要,如果没有这个标志位,我们每次在下拉到临界点的时候,都是重新走这个Down事件,这样永远也走不到move事件里面去了,所以这里我们只能执行一次dispatchTouchEvent里面的判断
看完了下拉过程,我们再来看看上拉,上拉的代码是在TouchEvent的move里面的
case MotionEvent.ACTION_MOVE:
scrollBy(0, lastY-y);
if (getScrollY()==mTopViewHeight && (lastY-y)>0) {
event.setAction(MotionEvent.ACTION_DOWN);
dispatchTouchEvent(event);
isInControl=false;
}
lastY=y;
break;
其实道理是一样的,将事件转化成down事件重新分发。有没有想过为什么这边不需要Cancel?因为任何一次完整的事件流都是上面DispatchTouchEvent说的算,至于你onTouchEvent里面是什么action,依然是DispatchTouchEvent来决定
最终效果