2.Android 高級UI<二>之事件分發機制&滑動沖突(2024精華版)

目錄:

1.事件分發機制是怎么樣的?

2.View與ViewGroup的事件分發有什么區別

3.onTouch和onTouchevent和onClick的執行順序?

4.如何理解消費?

5.Button和ImageView有什么不一樣?

6.可以達到父控件和子空間同時點擊嗎?

7.ListView上的button,點擊button2個控件同時要有相應,應該怎么處理?

點擊事件被攔截,但是相傳到下面的view,如何操作?

8.請簡述Android事件傳遞機制, ACTION_CANCEL事件何時觸發?

  1. 滑動沖突源碼分析

  2. 滑動沖突的幾種解決方案的使用場景?什么時候用內部攔截?

11. 滑動沖突實踐,實例: recleview嵌套recleview

1.事件分發機制是怎么樣的?

1.1 事件分發機制分為2種:View事件的分發和ViewGroup事件分發機制

總結ViewGroup發現:dispathcTouchEvent開始-----disallownotIntercepter---onInterceptTouchEvent-----1.子類dispath() 2.父類TouchEvent方法

viewGroup分發.jpg

然后我們來看一下View中dispatchTouchEvent方法的源碼:

public boolean dispatchTouchEvent(MotionEvent event) {
   if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
           mOnTouchListener.onTouch(this, event)) {
       return true;
   }
   return onTouchEvent(event);
}
1.2 view總結: 整個View的事件轉發流程是:(原理是dispatchTouchEvent)
public boolean dispatchTouchEvent(MotionEvent event) {
    if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
            mOnTouchListener.onTouch(this, event)) {
        return true;
    }
    return onTouchEvent(event);
}
1.3 完整的總結:
分發機制總圖.png

1). 事件分發機制是一種責任鏈模式, Android事件分發是先傳遞到ViewGroup,再由ViewGroup傳遞到View的。

2). 在ViewGroup中可以通過onInterceptTouchEvent方法對事件傳遞進行攔截,onInterceptTouchEvent方法返回true代表不允許事件繼續向子View傳遞,返回false代表不對事件進行攔截,默認返回false。

3). 子View中如果將傳遞的事件消費掉,ViewGroup中將無法接收到任何事件。

4). .在ViewGroup中onInterceptTouchEvent方法若反回false,那么觸屏事件會繼續向下傳遞,

但如果沒有子View去處理這個事件,即子view的onTouchEvent沒有返回True

則最后還是由ViewGroup去處理這個事件,也就又執行了自己的onTouchEvent。

備注: ViewGroup 類中,實際是沒有onTouchEvent 方法的,但是由于ViewGroup 繼承自View,

1.4 深層次的總結: (從InputChannel)

在attach()方法的時候,通過上面的流程圖我們知道,當我們的PhoneWindow創建完成之后,我們也在該Window上注冊了InputChannel并與IMS通信,

IMS把事件寫入InputChannel,WindowInputEventReceiver對事件進行處理并最終還是通過InputChannel反饋給IMS。

InputChannel最重要的!!!!!!!!

總結:兜兜轉轉一大圈我們神經都被繞彎了,我們在這里總結一下,當我們觸摸(點擊)屏幕時,

Android輸入系統IMS通過對事件的加工處理再合適的Window接收者并通過InputChannel向Window派發加工后的事件,

并觸發InputReceiver的onInputEvent的調用,由此產生后面一系列的調用,把事件派發給整個控件樹的根DecorView

而DecorView又上演了一出偷梁換柱的把戲,先把事件交給Activity處理,在Activity中又把事件交還給了我們的DecorView。自此沿著控件樹自上向下依次派發事件。

輸入事件 .jpg

2.View與ViewGroup的事件分發有什么區別

ViewGruop的事件分發:

多了一個攔截事件的方法:onInterceptTouchEvent

ViewGroup的dispathcTouchEvent方法:里面有onInterceptTouchEvent方法

區別表格.jpg

3.onTouch和onTouchevent和onClick的執行順序?

View.dispatchEvent----ontouch-----ontouchEvent(方法down,up,判斷onclick時間)---onclick
   
   
//子控件的ontouch方法影響子控件的函數
//onTouch====onTouchEvent====onClick;
/**
* 檢驗view的事件分發順序,點擊---dispatch-  Ontouch返回值為ture  不執行---ontouchEvent---onclick
*/
button1.setOnTouchListener(new View.OnTouchListener() {
   @Override
   public boolean onTouch(View v, MotionEvent event) {
       Log.d("TAG", "button1  on touch"+event.getAction());
       return true;
   }
});

/**
* 檢驗view的事件分發順序, 點擊---dispatch-  Ontouch返回值為false執行---ontouchEvent---onclick
*/
button2.setOnTouchListener(new View.OnTouchListener() {
   @Override
   public boolean onTouch(View v, MotionEvent event) {
       Log.d("TAG", "button1  on touch" + event.getAction());
       return false;
   }
});

ontouch先執行,如果返回true,ontouchEvent,onClick都不執行

ontouch先執行,如果返回false,ontouchEvent,然后再是onclick方法

如果不重寫onTouchListerner方法。

onTouchEvent如果返回true,不會執行onclick方法

onTouchEvent如果返回false,會執行onclick方法

onclick默認調用的是onTouchEvent。因為ontouch事件默認返回是false。那么就會響應onTochEvent。(onTouchEvent

總結:onTouch優先于onTouchEvent

1).看判斷條件。如果沒有mOnTouchListener ,ontouch不執行,onTouchEvent執行

2).如果有mOnTouchListener,并且onTouch =true,onTouchEvent不執行

  1. .如果有mOnTouchListener,并且onTouch =false,onTouchEvent執行

4.如何理解消費?view事件分發機制的案例

4.1 總結:

如果onTouch為true,代表消費了。不會執行onTouchevent了

如果子類的onTouchevent為true,代表消費了,父類不會執行onTouchevent

基本上就是返回true,就是消費了

4.2 案例說明
案例.jpg

當一個Touch事件(觸摸事件為例)到達根節點,即Acitivty的ViewGroup時,它會依次下發,下發的過程是調用子View(ViewGroup)的dispatchTouchEvent方法實現的。

簡單來說,就是ViewGroup遍歷它包含著的子View,調用每個View的dispatchTouchEvent方法,而當子View為ViewGroup時,又會通過調用ViwGroup的dispatchTouchEvent方法繼續調用其內部的View的dispatchTouchEvent方法。

上述例子中的消息下發順序是這樣的:①-②-⑤-⑥-⑦-③-④。

dispatchTouchEvent方法只負責事件的分發,它擁有boolean類型的返回值,當返回為true時,順序下發會中斷。

在上述例子中如果⑤的dispatchTouchEvent返回結果為true,那么⑥-⑦-③-④將都接收不到本次Touch事件

5.Button和ImageView有什么不一樣?

Button和ImageView效果不一樣:一個是自帶點擊,一個是要自己控制點擊

onTouch能夠得到執行需要兩個前提條件,第一mOnTouchListener的值不能為空,第二當前點擊的控件必須是enable的。因此如果你有一個控件是非enable的,

那么給它注冊onTouch事件將永遠得不到執行。對于這一類控件,如果我們想要監聽它的touch事件,就必須通過在該控件中重寫onTouchEvent方法來實現。

<wiz_code_mirror><pre class=" CodeMirror-line " role="presentation">/*ImageView默認是不能點擊事件的,要想點擊的話必須手動設置/</pre>

/**ImageView默認是不能點擊事件的,要想點擊的話必須手動設置*/
imageView.setClickable(true);

imageView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.e("TAG","imageView setOnTouchListener");
    }
});

6.可以達到父控件和子空間同時點擊嗎?

如下

7.ListView上的button,點擊button2個控件同時要有相應,應該怎么處理?

7.1 具體方案:在listView的OnInterceptTouchEvent()方法里面。判斷區域。是否攔截

在listView的空白區域:執行listview的onTouchEvent方法。攔截button

在button的點擊區域: 不攔截,消費button的onTouchEvent事件。

當父控件是布局而子控件是控件時,如果要設置點擊效果,可以在父布局里面加上android:clickable="true" ,在子控件里面設置android:clickable="false",并設置狀態跟隨父布局android:duplicateParentState="true",至于效果,則隨自己寫吧

7.2 案例分析4種情況:

1).如何讓子類只有觸摸事件,沒有點擊事件

2).如何讓子類既有觸摸事件又有點擊事件

3).如何讓父類只有觸摸事件,沒有點擊事件

4).如何讓父類既有觸摸事件又有點擊事件

分析總結:

  1. .onTouch為true,事件被消費了,ontouchevent不執行,點擊也就不會執行
button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("peng"," button.setOnTouchListener"+event.getAction());
        return true;
    }
});

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," button.setOnClickListener");
    }
});

2). onTouch為false,ontouchevent會執行,這樣,點擊事件會執行

button.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("peng"," button.setOnTouchListener"+event.getAction());
        return false;
    }
});

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," button.setOnClickListener");
    }

    
    默認情況下,子view的onTouchEvent返回true,消費
        
@Override
public boolean onTouchEvent(MotionEvent event) {
    boolean pass=super.onTouchEvent(event);
    Log.d("peng","onTouchEvent onTouchEvent"+pass);
    return pass;
}
  1. .父類想要響應,子類不能消費,onTouch false ,onTouchEvent 也為false,onTouch 為false
button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," button.setOnClickListener");
    }
});


viewHead.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Log.d("peng"," viewHead.setOnTouchListener"+event.getAction());
        return true;
    }
});

viewHead.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("peng"," viewHead.setOnClickListener");
    }
});

public class Myview extends android.support.v7.widget.AppCompatButton {
    public Myview(Context context) {
        super(context);
    }

    public Myview(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public Myview(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("peng","Myview onTouchEvent onTouchEvent"+false);
        return false;
    }
  1. .父類想要響應,子類不能消費,onTouch false ,onTouchEvent 也為false,onTouch 為false .父類的onTouchEvent也要重寫true,代表消費了。
@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.d("peng","MyParentView onTouchEvent");
    return true;
}

子控件拿到事件之后,先判斷是否設置了OnTouchListener, 如果設置了,則調用OnTouchListener的onTouch方法,如果返回true,事件已經處理到此結束,則跳過onTouchEvent方法,否則調用onTouchEvent方法

7.3 點擊事件被攔截,但是想傳到下面的view,如何操作?

反向制約:重寫子類的requestDisallowInterceptTouchEvent()方法返回true,就不會執行父類的onInterceptTouchEvent(),即可將點擊事件傳到下面的View。

7.4 我想讓webview在應用里面后臺運行?看不到界面

2個viewGoup

1個webview和一個ViewGroup(包含4個btn)

點擊btn的時候,會消費掉事件

問題:viewgroup點擊空白也是會有事件的,如何給他添加監聽

加入點擊空白頁面,Viewgroup的子View消費掉。(webview的子空間)

問題:不想讓子控件消費怎么做

1).可以自己消費掉,ontouch==true。不再傳遞了,onclick事件就不會執行

  1. .可以讓另外一個viewgourp自己消費掉。

ontouch==true,自己的onclick不會在執行,但是這個子view還是響應了

原因:因為沒有攔截,走了子類的dispathevent方法。子類的dispathevent----ontouch---子類的onclick方法消費了。

所以消費是onclick和ontouch方法,但是onclick方法也是要先調用ontouch---ontouchevnet----onclick。

總結:最后的消費指的時onTouch事件

7.5 有一個布局,然后有一個textview,然后想點擊整個布局有點擊事件

結果發現:點擊textview的區域沒有響應,因為textview把焦點占用了。為了讓整個區域都有效果的話,把textview設置成

android:clickable="false"
按鈕視圖.jpg
<TextView
    android:id="@+id/tv_sport_data_second_value"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textSize="@dimen/dp_20"
    android:textColor="@color/color_333333"
    android:textStyle="bold"
    android:clickable="false"
    android:text="0"
    android:layout_below="@id/ll_second_title"
    android:layout_marginTop="@dimen/dp_6"

<RelativeLayout
    android:id="@+id/rl_sport_data_second"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    >

    <LinearLayout
        android:id="@+id/ll_second_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center_vertical"
        >
        <TextView
            android:id="@+id/tv_sport_data_second_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/color_333333"
            android:textSize="@dimen/dp_14"
            android:text="@string/string_sport_rank_total_sport"
            ></TextView>

8.請簡述Android事件傳遞機制, ACTION_CANCEL事件何時觸發?

1). 關于ACTION_CANCEL何時被觸發,系統文檔有這么一種使用場景:在設計設置頁面的滑動開關時,如果不監聽ACTION_CANCEL,在滑動到中間時,如果你手指上下移動,就是移動到開關控件之外,則此時會觸發ACTION_CANCEL,而不是ACTION_UP,造成開關的按鈕停頓在中間位置。
意思是當滑動的時候就會觸發,不知道大家搞沒搞過微信的長按錄音,有一種狀態是“松開手指,取消發送”,這時候就會觸發ACTION_CANCEL。

2). 簡單來說不是一個完整的手勢響應 例如:子控件只是響應了down 而父控件把子控件的up事件攔截了 這個時候就會觸發cancel事件。

詳細:當控件收到前驅事件(什么叫前驅事件?一個從DOWN一直到UP的所有事件組合稱為完整的手勢,中間的任意一次事件對于下一個事件而言就是它的前驅事件)之后,后面的事件如果被父控件攔截,那么當前控件就會

9. 滑動沖突源碼分析

10. 滑動沖突的幾種解決方案的使用場景?什么時候用內部攔截?

10. 1 外部攔截法:(根據自己的業務攔截子view),重寫一個方法

即父View根據需要對事件進行攔截。邏輯處理放在父View的onInterceptTouchEvent方法中。我們只需要重寫父View的onInterceptTouchEvent方法,并根據邏輯需要做相應的攔截即可。

public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                intercepted = false;
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                if (滿足父容器的攔截要求) {
                    intercepted = true;
                } else {
                    intercepted = false;
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                intercepted = false;
                break;
            }
            default:
                break;
        }
        mLastXIntercept = x;
        mLastYIntercept = y;
        return intercepted;
    }

注意點:

1). ACTION_DOWN 一定返回false,不要攔截它,否則根據View事件分發機制,后續ACTION_MOVE 與 ACTION_UP事件都將默認交給父View去處理!

2). ACTION_MOVE方法中進行判斷,根據業務邏輯需要,如果需要父View處理則返回true,否則返回false,事件分發給子View去處理。

3). ACTION_UP也需要返回false,如果返回true,并且滑動事件交給子View處理,那么子View將接收不到ACTION_UP事件,子View的onClick事件也無法觸發。

  • 而父View不一樣,如果父View在ACTION_MOVE中開始攔截事件,那么后續ACTION_UP也將默認交給父View處理!
  • 可以直接用super。默認都是不攔截
可以直接用super。默認都是不攔截
/***
 * 如果不寫整個方法的話:就會響應子類的touchEvent方法,而不響應自己viewGroup的方法
 * @param
 * @return
 */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN://0
            mXDown = ev.getRawX();
            mXLastMove = mXDown;
            break;
        case MotionEvent.ACTION_MOVE://2
            mXMove = ev.getRawX();//獲取相對于屏幕的x值
            float diff = Math.abs(mXMove - mXDown);
            mXLastMove = mXMove;
            // 當手指拖動值大于TouchSlop值時,認為應該進行滾動,攔截子控件的事件
            if (diff > mTouchSlop) {
                return true;
            }
            break;
        case MotionEvent.ACTION_UP://1
            break;
    }

    boolean superResult = super.onInterceptTouchEvent(ev);
    Log.d("ScrollerLayout", "superResult" + superResult+"ev"+ev.getAction());
    return superResult;
}

具體:

1.down 不攔截,否則up收不到,點擊事件也會沒有

2.move 更加業務判定。得到子view,滑動的距離和item的位置決定

3.up 不攔截

10.1.2 具體案例寫法

@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean intercepted = false;
    int y = (int) event.getY();

    switch (event.getAction()) {

        case MotionEvent.ACTION_DOWN: {
            nowY = y;
            intercepted = super.onInterceptTouchEvent(event);
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            if(mListView.getFirstVisiblePosition()==0
                    && y>nowY){
                intercepted = true;
                break;
            }
            else if(mListView.getLastVisiblePosition()==mListView.getCount()-1
                    && y<nowY){
                intercepted = true;
                break;
            }
            intercepted = false;
            break;
        }
        case MotionEvent.ACTION_UP: {
            intercepted = false;
            break;
        }
        default:
            break;
    }

    return intercepted;
} 

10.2 內部攔截法:(攔截子view) (重寫2個方法,都是事件分發的方法)

即父View不攔截任何事件,所有事件都傳遞給子View,子View根據需要決定是自己消費事件還是給父View處理。這需要子View使用requestDisallowInterceptTouchEvent方法才能正常工作。下面是子View的dispatchTouchEvent方法的偽代碼:

1). 父View需要重寫onInterceptTouchEvent方法:

為什么要重寫父類的 onInterceptTouchEvent?因為默認不攔截,你需要的是攔截它

 public boolean onInterceptTouchEvent(MotionEvent event) {

        int action = event.getAction();
        if (action == MotionEvent.ACTION_DOWN) {//down不攔截,給子類
            return false;
        } else {//攔截
            return true;
        }
    }

2). 重寫子類的dispatchTouchEvent()方法

 public boolean dispatchTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                parent.requestDisallowInterceptTouchEvent(true); // 父類不攔截, 子類處理
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if (父容器需要此類點擊事件) {
                    parent.requestDisallowInterceptTouchEvent(false);//請求父類攔截, 父類處理
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                break;
            }
            default:
                break;
        }

        mLastX = x;
        mLastY = y;
        return super.dispatchTouchEvent(event);
    }

10.2.1 內部攔截法總結:

1). 父View不能攔截ACTION_DOWN事件,由于ACTION_DOWN不受FLAG_DISALLOW_INTERCEPT標志位控制,一旦父容器攔截ACTION_DOWN那么所有的事件都不會傳遞給子View。

2). View的dispatchTouchEvent方法的ACTION_DOWN中, parent.requestDisallowInterceptTouchEvent(true)2). 滑動策略的邏輯放在子View的dispatchTouchEvent方法的ACTION_MOVE中,如果父容器需要獲取點擊事件則調用 parent.requestDisallowInterceptTouchEvent(false)方法,讓父容器去攔截事件。如果不需要,則相反

10.2.2 內部攔截法原理:

1). 內部攔截法也叫View分發反向制約的方法? 2). 攔截不攔截,由2個東西決定的。一個是requestDisllowIntercepter和onInterceptTouchEvent()2個決定的。

原因:但是子元素可以通過requestDisallowInterceptTouchEvent來干預父元素的分發過程,但是down事件除外(因為down事件方法里,會清除所有的標志位)。

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    if (mInputEventConsistencyVerifier != null) {
        mInputEventConsistencyVerifier.onTouchEvent(ev, 1);
    }

    // If the event targets the accessibility focused view and this is it, start
    // normal event dispatch. Maybe a descendant is what will handle the click.
    if (ev.isTargetAccessibilityFocus() && isAccessibilityFocusedViewOrHost()) {
        ev.setTargetAccessibilityFocus(false);
    }

if (actionMasked == MotionEvent.ACTION_DOWN
        || mFirstTouchTarget != null) {
    final boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
    if (!disallowIntercept) {
        intercepted = onInterceptTouchEvent(ev);
        ev.setAction(action); // restore action in case it was changed
    } else {
        intercepted = false;
    }

10.3 從內容逆向思維分析

1). 有時候,我們不想去修改引入的第三方控件,或者說是無法修改時。就必須考慮從當前從Touch傳遞事件中最后的那個View逆向考慮。

首先,由Android中View的Touch事件傳遞機制,我們知道Touch事件,首先必然由最外層View攔截,如果無法更改這個最外層View,那么是不是就沒轍了呢?

其實不然,Android這么高大上的系統必然考慮到了這個問題,好了廢話不說,先看代碼

解決方案:onTouch方法中每次進入就設定父View不攔截此次事件,然后在MOTION_MOVE時候,根據滑動的距離判斷再決定是父View是否有權利攔截Touch事件(即滑動行為)。

    carouselView.setOnTouchListener( new View.OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            carouselView.getParent().requestDisallowInterceptTouchEvent( true );
            int x = ( int ) event.getRawX();
            int y = ( int ) event.getRawY();

            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break ;
                case MotionEvent.ACTION_MOVE:
                int deltaY = y - lastY;
                int deltaX = x - lastX;
                if (Math.abs(deltaX) < Math.abs(deltaY)) {
                    carouselView.getParent().requestDisallowInterceptTouchEvent( false );
                } else {
                    carouselView.getParent().requestDisallowInterceptTouchEvent( true );
                }
                default :
                break ;
            }
            return false ;
        }
}
2). 一個viewpager2里面放了很多圖片。但是圖片又可以大于屏幕,導致滑動沖突。瀏覽圖片 ViewPager2和HorizontalScrollView滑動沖突 結果:Viewpager2不能重新怎么辦?它是final類。導致內部攔截和外部攔截不適用!

重寫onTouchListener();

10.4 down,move ,Up,都是否需要攔截總結?

1). ACTION_DOWN,都不要攔截子類

在這里,首先down事件父容器必須返回false ,因為若是返回true,也就是攔截了down事件,

那么后續的move和up事件就都會傳遞給父容器,子元素就沒有機會處理事件了。

其次是up事件也返回了false,一是因為up事件對父容器沒什么意義,其次是因為若事件是子元素處理的,卻沒有收到up事件會讓子元素的onClick事件無法

2). 要在MotionEvent.ACTION_MOVE根據情況,是父類滑動還是子類滑動

10.5 滑動沖突的幾種解決方案的使用場景?什么時候用內部攔截?

主要用內部攔截,系統里面的,horscorrlview和,比如recyleview.

原因: 你只能重新你可以的, 能達到的view(主要看你哪個View是你自己的)

11. 滑動沖突實踐,實例: recleview嵌套recleview

11. 1 一個ScrowView(父類)和一個RecycleView(子類)

他說重寫子類的onIntecepter方法,讓子類攔截,消費掉

11.2 ViewPager中嵌套ViewPager怎么處理滑動沖突?

1).重寫canScroll()方法

2).自己手寫
11.3 一個scorview和一個日期選擇器
分析:scorllView是父類,datapinker是子類(viewGroup)

現在現象:在分辨率比較小的手機中,有時候滑動scorllView,有時候滑動dataPinker

需要實現的效果:攔截scorllView。超過1屏的時候,自己滑動

private void doMove(MotionEvent event)
{

    mMoveLen += (event.getY() - mLastDownY);

    if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2)
    {
        // 往下滑超過離開距離
        moveTailToHead();
        mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;
    } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2)
    {
        // 往上滑超過離開距離
        moveHeadToTail();
        mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;
    }

    mLastDownY = event.getY();
    invalidate();
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容