java - llamar - navigation drawer material design
¿Por qué DrawerLayout a veces falla al abrirse? (2)
He seguido el tutorial Cajón de navegación y todo funciona como un amuleto excepto por un pequeño error. Trataré de explicarlo lo más posible, y si aún no está claro, intentaré subir un video del problema.
El problema ocurre cuando se intenta abrir el cajón y solo cuando se abre, y solo sucede a veces, no siempre. Entonces, cuando empiezo a abrirlo, falla y se congela con unos 4 milímetros abiertos y siempre a la misma distancia. Entonces no continuaría abriendo ni retrocediendo si muevo mi dedo hacia atrás, cuando lo suelte, se cierra.
Tenga en cuenta:
- Lo probé en múltiples dispositivos (Nexus 7, Nexus) y también en dispositivos virtuales, el problema persiste.
- Problema replicado utilizando el ejemplo provisto por Google. (Enlace de YouTube)
- Problema presentado con mi aplicación. (Enlace de YouTube)
- Logré replicar el problema una vez, pero solo una vez en la aplicación de Gmail (que creo que usa la misma implementación), aunque mucho más frecuente con mi aplicación y la de ejemplo.
- Me di cuenta de que la falla ocurre a la misma distancia de la que se abre el cajón si solo hace clic en el borde de la pantalla, ya que se congela después de la apertura inicial y nunca se arrastra.
Cualquier indicador sería apreciada.
Investigué el código de DrawerLayout
y encontré el siguiente número: cuando tocamos el borde de la pantalla aparece una pequeña (20 * densidad px) parte del drawer
(hace que mover el cajón sea más fácil). No aparece inmediatamente, pero después de un cierto intervalo (160 ms) de tiempo. Se realiza por postDelayed
.
El drawer
puede estar en varios estados: IDLE
, DRAGGING
y DRAGGING
. Si estaba en el estado DRAGGING
, ya no puede volver a este estado con el mismo puntero y borde (porque hay una condición: mEdgeDragsInProgress[pointerId] & edge) == edge
que no permite arrastrar el borde que se ha arrastrando ya).
Entonces, en algunos casos, el cajón se ha movido al estado DRAGGING
ya cuando se está ejecutando el Runnable
retrasado. Esta acción retrasada abre el drawer
para 20 * densidad px y cambia el estado del drawer
. Por lo tanto, el drawer
ya no puede moverse (porque no puede volver al estado DRAGGING
).
Hay un código para cancelar la acción retrasada (que abre el cajón), pero este código en el método onInterceptTouchEvent
, que se llama una sola vez (porque devuelve false
). Creo que este código debe estar en el método onTouchEvent
.
Desgraciadamente, no encontré ninguna forma de cancelar el evento retrasado (porque tiene private
modificador private
y no puedo obtenerlo). Entonces, solo una forma que encontré: copiar el código fuente de DrawerLayout
a mi proyecto y hacer este pequeño cambio: copiar
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;
}
desde el método onInterceptTouchEvent
al método onTouchEvent
.
No hay ningún error en el archivo drawerlayout. Simplemente agregue un ScrollView como vista principal o raíz al archivo y herramientas content.xml (setcontentview file): context = ". MainActivity"