需求:App 同時實現「左側滑出菜單」與「ViewPager 內容頁左右滑動切換」。核心衝突:**DrawerLayout 攔截觸摸事件導致 ViewPager 無法滑動**,或 ViewPager 消費事件導致側滑菜單打不開。本文給出 Google 官方推薦的協調方案。
DrawerLayout 內部 onInterceptTouchEvent 判斷邊緣滑動開啟菜單。ViewPager 內部 onTouchEvent 處理頁面切換滑動。<androidx.drawerlayout.widget.DrawerLayout
xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 主內容:ViewPager -->
<androidx.viewpager.widget.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- 側滑菜單 (左側) -->
<com.google.android.material.navigation.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
app:menu="@menu/drawer_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int state) {
// 關鍵:ViewPager 開始拖動時,禁止 DrawerLayout 攔截
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
drawerLayout.requestDisallowInterceptTouchEvent(true);
} else {
// 滑動結束/空閒時,恢復 DrawerLayout 攔截權限
drawerLayout.requestDisallowInterceptTouchEvent(false);
}
}
// onPageScrolled, onPageSelected 可留空
});
// 可選:邊緣滑動閾值優化(預設 20dp,可調大觸發側滑靈敏度)
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
public class SmartViewPager extends ViewPager {
public SmartViewPager(Context context, AttributeSet attrs) { super(context, attrs); }
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// 第一頁靠左邊緣、最後頁靠右邊緣,允許父容器攔截 (開啟側滑/右側菜單)
if (getCurrentItem() == 0 && ev.getX() < getWidth() * 0.1f) return false;
if (getCurrentItem() == getAdapter().getCount() - 1 && ev.getX() > getWidth() * 0.9f) return false;
return super.onInterceptTouchEvent(ev);
}
}
onTouchEvent 返回 false 破壞事件鏈。requestDisallowInterceptTouchEvent(true) 必須在 SCROLL_STATE_DRAGGING 時調用,SETTLING/IDLE 時釋放。FragmentStatePagerAdapter,注意 Fragment 生命週期與觸摸事件的關係。掌握 requestDisallowInterceptTouchEvent 這個「事件分發協調開關」,側滑菜單與 ViewPager 完美共存。