Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does DrawerLayout sometimes glitch upon opening?

I have followed the tutorial Navigation Drawer and everything works like a charm except for a small glitch. I'll try to explain it as much as possible, and if it still isn't clear, I'll try to upload a video of the problem.

Problem happens when trying to open the drawer and only when opening, and only happens sometimes, not always. That is when I start to open it it glitches and freezes with about 4 millimeters open, and always the same distance. It then would not continue opening nor close back if I move my finger back, when I let go, it closes.

Please note:

  • I have tried it on multiple devices (Nexus 7, Nexus) and virtual devices as well, problem persists.
  • Issue replicated using the example provided by Google. (Youtube Link)
  • Issue presented with my app. (Youtube Link)
  • I managed to replicated the issue once but only once in Gmail app (which I believe uses the same implementation), however much more frequent with my app and the sample app.
  • I noticed that the glitch happens at the same distance of which the drawer opens if you just click the edge of the screen, as in it freezes after initial open and never drags.

Any pointers would be appreciated.

like image 354
LuckyMe Avatar asked Jul 27 '13 08:07

LuckyMe


People also ask

How do you use DrawerLayout?

To use a DrawerLayout, position your primary content view as the first child with width and height of match_parent and no layout_gravity> . Add drawers as child views after the main content view and set the layout_gravity appropriately. Drawers commonly use match_parent for height with a fixed width.

How do you change the DrawerLayout icon on the right side of the device screen?

Edit. According to Creating a Navigation Drawer, The drawer view (the ListView) must specify its horizontal gravity with the android:layout_gravity attribute. To support right-to-left (RTL) languages, specify the value with "start" instead of "left" (so the drawer appears on the right when the layout is RTL).

What is DrawerLayout?

Drawer Layout In Android: In Android, DrawerLayout acts as top level container for window content that allows for interactive “drawer” views to be pulled out from one or both vertical edges of the window.


2 Answers

I researched the code of DrawerLayout and found the next issue: When we touch the edge of screen there appears small (20*density px) part of the drawer (it makes moving drawer easier). It doesn't appears immediatly, but after a certain interval (160 ms) of time. It is realized by postDelayed.

The drawer can be in several states: IDLE, DRAGGING and SETTLING. If it was in the DRAGGING state, it cannot return to this state anymore with the same pointer and edge (because there is a condition: mEdgeDragsInProgress[pointerId] & edge) == edge which doesn't allow to drag the edge which have been dragging already).

So in some cases the drawer have moved to the state DRAGGING already when delayed Runnable is executing. This delayed action opens drawer for 20*density px and change state of drawer. So drawer cannot be moved anymore (because it cannot return to the state DRAGGING).

There is a code for cancelling delayed action (which opens drawer), but this code in the method onInterceptTouchEvent, which is called only once (because it returns false). I think this code should be in the method onTouchEvent.

Unfortunatly I didn't find any way to cancel delayed event (because it has private modifier and I can't get it). So only one way I found: copy the source code of DrawerLayout to my project and make this small change: 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;         } 

from the method onInterceptTouchEvent to the method onTouchEvent.

like image 130
esentsov Avatar answered Sep 24 '22 07:09

esentsov


There is no error in drawerlayout file. Just add a ScrollView as the parent or root view to the content.xml(setcontentview file) file and tools:context=".MainActivity"

like image 43
Lakshay Khosla Avatar answered Sep 20 '22 07:09

Lakshay Khosla