Подтвердить что ты не робот

Почему DrawerLayout иногда сбой при открытии?

Я следил за учебником Ящик навигации, и все работает как шарм, за исключением небольшого сбоя. Я попытаюсь объяснить это как можно больше, и если все еще не ясно, я постараюсь загрузить видео с проблемой.

Проблема возникает при попытке открыть ящик и только при открытии и происходит иногда, не всегда. То есть, когда я начинаю открывать его, он глючит и замерзает с открытием 4 мм и всегда на таком же расстоянии. Тогда он не будет продолжать открываться и закрываться, если я отдержу палец назад, когда я отпущу, он закрывается.

Обратите внимание:

  • Я пробовал его на нескольких устройствах (Nexus 7, Nexus) и виртуальных устройствах, проблема сохраняется.
  • Проблема реплицируется с использованием примера, предоставленного Google. (Youtube Link)
  • Проблема с моим приложением. (Youtube Link)
  • Мне удалось воспроизвести проблему один раз, но только один раз в приложении Gmail (которое, как я полагаю, использует ту же реализацию), однако гораздо чаще с моим приложением и образцом приложения.
  • Я заметил, что сбой происходит на том же расстоянии, на котором открывается ящик, если вы просто нажимаете на край экрана, так как в нем зависает после первоначального открытия и никогда не перетаскивается.

Любые указатели будут оценены.

4b9b3361

Ответ 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.

Ответ 2

В файле drawerlayout нет ошибки. Просто добавьте ScrollView в качестве родительского или корневого представления в файл content.xml(файл setcontentview) и инструменты: контекст = "MainActivity"