HorizontalScrollView (HSV) 包裹 ListView 時,手指稍微偏移 X 軸就觸發水平滑動,導致垂直列表難以滑動。核心思路:垂直滑動時攔截觸摸事件,禁止 HSV 消費。
public class VerticalListView extends ListView {
private int mLastY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = (int) ev.getY();
getParent().requestDisallowInterceptTouchEvent(true); // 關鍵:搶奪攔截權
break;
case MotionEvent.ACTION_MOVE:
int deltaY = Math.abs((int) ev.getY() - mLastY);
if (deltaY > 10) // 垂直位移超過閾值
getParent().requestDisallowInterceptTouchEvent(true);
else
getParent().requestDisallowInterceptTouchEvent(false); // 釋放給 HSV
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return super.onInterceptTouchEvent(ev);
}
}
hsv.setOnTouchListener((v, event) -> {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
// 判斷是否為垂直滑動意圖,返回 true 消費事件阻止 HSV 滑動
}
return false;
});
requestDisallowInterceptTouchEvent(true):子 View 要求父 View 不得攔截 觸摸事件,強制由子 View 處理。onInterceptTouchEvent:ViewGroup 決定是否攔截事件分發給子 View。10px 需根據密度調整:dp2px(10)。ACTION_DOWN 判斷點擊區域,避免誤觸發攔截。RecyclerView + NestedScrollingParent 機制,原生支援嵌套滑動協調。一行 requestDisallowInterceptTouchEvent(true),讓雙向滑動各安其位。