Ответ 1
Я исследовал код DrawerLayout
и нашел следующую проблему:
Когда мы касаемся края экрана, появляется небольшая (20 * плотность px) часть drawer
(облегчает передвижение). Он появляется не сразу, а через определенный интервал (160 мс) времени. Это реализуется postDelayed
.
drawer
может находиться в нескольких состояниях: IDLE
, DRAGGING
и SETTLING
. Если он находился в состоянии DRAGGING
, он больше не может вернуться к этому состоянию с тем же указателем и ребер (потому что существует условие: mEdgeDragsInProgress[pointerId] & edge) == edge
, которое не позволяет перетаскивать уже перетаскиваемый край).
Итак, в некоторых случаях ящик переместился в состояние DRAGGING
уже при выполнении задержки Runnable
. Это отложенное действие открывает drawer
для плотности 20 px px и состояния изменения drawer
. Поэтому drawer
больше не может перемещаться (потому что он не может вернуться в состояние DRAGGING
).
Существует код для отмены замедленного действия (который открывает ящик), но этот код в методе onInterceptTouchEvent
, который вызывается только один раз (потому что он возвращает false
). Я думаю, что этот код должен быть в методе onTouchEvent
.
К сожалению, я не нашел способа отменить задержанное событие (потому что у него есть модификатор private
, и я не могу его получить). Итак, только один способ, который я нашел: скопируйте исходный код DrawerLayout
в мой проект и сделайте это небольшое изменение: copy
case MotionEvent.ACTION_MOVE: {
// If we cross the touch slop, don't perform the delayed peek for an edge touch.
if (mLeftDragger.checkTouchSlop(ViewDragHelper.DIRECTION_ALL)) {
mLeftCallback.removeCallbacks();
mRightCallback.removeCallbacks();
}
break;
}
из метода onInterceptTouchEvent
к методу onTouchEvent
.