美文网首页Android-ui效果自定义控件UI效果仿写
悬浮导航栏StickyNavLayout的实现--如何实现滑动不

悬浮导航栏StickyNavLayout的实现--如何实现滑动不

作者: 皮球二二 | 来源:发表于2016-05-27 22:01 被阅读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来决定

最终效果

相关文章

网友评论

  • Li小强:楼主,那段dispatch。。。下拉代码里面 if 的那个 isTopHidden 应该是 !isTopHidden才对吧?因为下拉直到蓝色区域全部显示才cancel然后重新down吧?:pray:
    皮球二二: @Li小强 不是,是蓝色出现的临界点
  • ca7c426ed84d:你确定你是对鸿洋代码解读???
    package com.rg.stickynavlayout.view;

    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.VelocityTracker;
    import android.view.View;
    import android.view.ViewConfiguration;
    import android.widget.LinearLayout;
    import android.widget.ListView;
    import android.widget.OverScroller;

    import com.rg.stickynavlayout.R;

    /**
    * Created by RG on 2016/5/19.
    */
    public class StickyNavLayout extends LinearLayout {
    这是你的

    package com.zhy.stickynavlayout.view;

    import android.content.Context;
    import android.support.v4.view.NestedScrollingParent;
    import android.support.v4.view.ViewCompat;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.VelocityTracker;
    import android.view.View;
    import android.view.ViewConfiguration;
    import android.view.ViewGroup;
    import android.widget.LinearLayout;
    import android.widget.OverScroller;

    import com.zhy.stickynavlayout.R;


    public class StickyNavLayout extends LinearLayout implements NestedScrollingParent
    这是鸿洋的,你确定你们用的是同一个东西?
    皮球二二: @尾戒o 他现在已经改成coordinatorLayout的那种嵌套滑动了,你可以看看他之前的commit,之前他是自定义ViewGroup的
  • 20501f08caef:楼主能详细说下为什么上拉不需要Action_Cancel吗,按理说不是都应该在dispatchTouchEvent里统一处理逻辑吗,为什么上拉要写在onTouchEvent里?
    皮球二二: @lovexx 你好,我的理解是这样的,这里dispatch不处理cancel是因为onIterceptTouchEvent跟onTouchEvent已经处理了cancel的情况,所以直接传递下去复用代码就行。至于你说代码都放在dispatch里面,我认为他仅仅是处理分发过程,不应该都混在一起,要不然谷歌分这么细干嘛呢

本文标题:悬浮导航栏StickyNavLayout的实现--如何实现滑动不

本文链接:https://www.haomeiwen.com/subject/ybdfdttx.html