Scrollview 和 內部 recycleview 高度固定時巢狀衝突的一種解決方法

阿里我的兜發表於2018-04-09

瞭解事件分發機制就很容易瞭解原理,就是在子view需要處理滑動事件時,父view則不對事件進行攔截處理交由子view進行事件處理,而在父view需要處理時則進行攔截處理,不讓子view處理。

1.首先自定義scrollview,onInterceptTouchEvent方法就是攔截方法,返回true則代表攔截,不讓自view進行處理,返回false,代表讓子view 進行處理。

public class ScrollViewWithListener extends ScrollView {
      private ScrollViewListener scrollViewListener;
      private onSrcollviewToBottoListener onSrcollviewToBottomListener;
     private boolean isBotoom=false;//是否滑動到底部
     private boolean isTop=false;//是否內部listview滑動到頂部
     public ScrollViewWithListener(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (ev.getAction()==MotionEvent.ACTION_DOWN) {
            Log.v("action_down",ev.toString());
            if(isTop&&isBotoom){
                Log.v("同時觸及",isTop+""+isBotoom);
                return  false;
            }
            return super .onInterceptTouchEvent(ev);
        }else if (ev.getAction()==MotionEvent.ACTION_MOVE) {

            Log.v("截斷",isTop+""+isBotoom);
            if (isTop) {
                return  super.onInterceptTouchEvent(ev);

            }else if (isBotoom) {//如果是底部交由子view處理
                return false;
            }
        } else if(ev.getAction()==MotionEvent.ACTION_UP){
            Log.v("action_up",ev.toString());
            return false;
        }

        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return super.onTouchEvent(ev);
    }
  
    public ScrollViewWithListener(Context context) {
        super(context);
    }

    public ScrollViewWithListener(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }



    public void setScrollViewListener(ScrollViewListener scrollViewListener) {
        this.scrollViewListener = scrollViewListener;
    }

       public   void setOnToBottomListenr(onSrcollviewToBottomListener onSrcollviewToBottomListener){
           this.onSrcollviewToBottomListener=onSrcollviewToBottomListener;

       }

    @Override
    protected void onScrollChanged(int x, int y, int oldx, int oldy) {
       View  view=getChildAt(getChildCount()-1);
        int d=view.getBottom();
        d-=getHeight()+getScrollY();
        if (d==0){//判斷是否為底部
            if (onSrcollviewToBottomListener!=null){
            onSrcollviewToBottomListener.onScrollToBottom(true);}
            isBotoom=true;
        }else {
            if (oldy-y!=0){
                isBotoom=false;
            }

            super.onScrollChanged(x, y, oldx, oldy);
        }



        if (scrollViewListener != null) {
            scrollViewListener.onScrollChanged(this, x, y, oldx, oldy);
        }
    }
     public void  setIsTop(boolean istop){
      this.isTop=istop;
     }
      public interface onSrcollviewToBottomListener{
         void onScrollToBottom(boolean isBotoom );
  }

}
複製程式碼

2.對子view 的listview 滑動監聽。並且回撥結處理結果。

   private OnTopListener onTopListener;
private void setScrollViewMoveWhenListViewStopMoving(ListView lv_hot_service) {
        lv_hot_service.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState){
                    case AbsListView.OnScrollListener.SCROLL_STATE_IDLE:
                       if (view.getLastVisiblePosition()==(view.getCount()-1)){
                           Log.v("到底了","到底了");
                    }
                       if (view.getFirstVisiblePosition()==0){
                           onTopListener.viewIsTop(true);
                           Log.v("vvvvvvvvvv","到頂了"+isListviewTop);
                       }else {
                           onTopListener.viewIsTop(false);
                           Log.v("vvvvvvvvvv","在中間"+isListviewTop);
                       }
                       break;
                    case  AbsListView.OnScrollListener.SCROLL_STATE_FLING:
                        onTopListener.viewIsTop(false);
                        break;
                    case  AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
                        onTopListener.viewIsTop(false);
                        break;
                }
            }
            @Override
 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

  }
    });

 public void setOnTopListener(OnTopListener onTopListener){
        this.onTopListener=onTopListener;
    }
    }
複製程式碼

然後將listview的滑動結果傳遞給父view srcollview進行處理。

scrollListener.setOnToBottomListenr(new ScrollViewWithListener.onSrcollviewToBottomListener() {
            @Override
            public void onScrollToBottom(boolean isBotoom) {
                if (isBotoom) {
                    isListviewTop = false;//記錄到底而讓listview 接管監聽
                    onTopListener.viewIsTop(false);
                    Log.v("scrollview到底了","到底了");
                }
            }
        });
複製程式碼

雖然簡單的解決了一下問題但還是存在一些問題 記錄下自己接下來再更改。

相關文章