2013-07-27 3 views
26

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

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

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

  • Я пробовал на нескольких устройствах (Nexus 7, Nexus) и виртуальных устройств, а также, проблема сохраняется.
  • Issue replicated using the example provided by Google. (Youtube Link)
  • Issue presented with my app. (Youtube Link)
  • мне удалось воспроизвести этот вопрос один раз, но только один раз в приложении Gmail (который я считаю использует ту же реализацию), однако гораздо чаще с моим приложением и пример приложения.
  • Я заметил, что сбой происходит на том же расстоянии, на котором открывается ящик, если вы просто щелкаете по краю экрана, так как в нем замерзает после первоначального открытия и никогда не тянет.

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

+1

Можете ли вы приложить скриншот? – PravinCG

+0

Это происходит, если вы открываете меню, передвигаясь с границы или нажав значок (при условии, что вы внедрили эту функцию) или в обоих случаях? Вы проверили logcat для каких-либо исключений? Я никогда не видел ничего подобного, и я тестировал около 10 устройств. Какую версию библиотеки поддержки вы используете? ** p.s. **: Этот эффект также появляется в примере приложения? (см. http://developer.android.com/training/implementing-navigation/nav-drawer.html) – Trinimon

+0

@Trinimon Случается только путем скольжения. Logcat ничего не представляет. Использовал предыдущую библиотеку поддержки и просто сделал обновление, которое было выпущено в последнее время, и это все еще происходит (версия 18). Я добавил видео к исходному вопросу, если вы хотите его проверить. – LuckyMe

ответ

23

Я исследовал код DrawerLayout и нашел следующий вопрос: Когда мы прикасаемся к краю экрана появляется маленькой (20 * плотность точек) часть drawer (это делает перемещение ящика проще). Он появляется не сразу, а через определенный интервал (160 мс) времени. Он реализуется postDelayed.

drawer может быть в нескольких штатах: IDLE, DRAGGING и SETTLING. Если он находился в состоянии DRAGGING, он больше не может вернуться в это состояние с тем же указателем и ребер (потому что существует условие: mEdgeDragsInProgress[pointerId] & edge) == edge, которое не позволяет перетаскивать уже перетаскиваемый край).

Так что в некоторых случаях ящик переместился в состояние DRAGGING уже при отсрочке Runnable. Это отложенное действие открывается drawer для 20 * плотности px и изменение состояния drawer. Так что drawer больше не может быть перемещен (потому что он не может вернуться в состояние DRAGGING).

Существует код для отмены отложенного действия (который открывает ящик), но этот код в методе onInterceptTouchEvent, который вызывается только один раз (потому что он возвращает false). Я думаю, что этот код должен быть в методе onTouchEvent.

К сожалению, я не нашел способа отменить задержанное событие (потому что у него есть модификатор private, и я не могу его получить). Таким образом, только один способ, которым я нашел: скопировать исходный код DrawerLayout в мой проект и сделать это небольшое изменение: скопировать

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.

+0

Отличные исследования, реквизиты для перехода на следующий уровень. Просто следуйте за этим, так что 'DelayedRunnable 'when execute изменяет состояние на' SETTLING', затем 'DRAGGING'? Или просто на' DRAGGING', но затем он глючит, потому что состояние менялось с 'DRAGGING' на' DRAGGING', когда ag айн? – LuckyMe

+1

Как я понимаю, состояние 'DRAGGING' -' drawer' следует за пальцем, состояние 'SETTLING' -' drawer' перемещается с постоянной скоростью, например. когда мы отпускаем его посередине, он продолжает двигаться, чтобы закрыть или открыть). 'DelayedRunnable' изменяет состояние на' SETTLING' (потому что это просто анимация, 'drawer' не следует пальцем). – esentsov

+3

Другим обходным решением является использование android: clickable = "true" в основном содержимом FrameLayout. http://stackoverflow.com/questions/18044277/android-navigation-drawer-bug-using-the-sample –

1

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

+1

У этого вопроса уже был ответ, который был принят - посмотрев на другие ответы, вы должны действительно представить только поздний ответ, когда почувствуете, что ваш ответ добавляет большую ценность (например, используя самые последние утилиты/библиотеки, видя, что вопрос 3 года). – ishmaelMakitla

+0

но я не думаю, что разрешил проблему здесь –

Смежные вопросы