Home » Android » android – DrawerLayout getting stuck on swipe

android – DrawerLayout getting stuck on swipe

Posted by: admin April 23, 2020 Leave a comment

Questions:

I am playing around with DrawerLayout and I am encountering an issue. Basically sometimes when i swipe from the edge of the screen the DrawerLayout will get stuck until i lift my finger off the screen (See screenshot below)

I am not sure what is up, I followed the code sample from the google sdk exactly. Any ideas?

Screenshot bug

And here is the only thing i have in my FragmentActivity:

@Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final String[] names =
                getResources().getStringArray(R.array.nav_names);
        ArrayAdapter<String> adapter =
                new ArrayAdapter<String>(
                        getActionBar().getThemedContext(),
                        android.R.layout.simple_list_item_1, names);

        final DrawerLayout drawer =
                (DrawerLayout)findViewById(R.id.drawer_layout);
        final ListView navList =
                (ListView) findViewById(R.id.drawer);
        navList.setAdapter(adapter);
        navList.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {

            @Override
            public void onItemClick(AdapterView<?> parent,
                                    View view, final int pos, long id)
            {
                drawer.setDrawerListener(
                        new DrawerLayout.SimpleDrawerListener()
                        {
                            @Override
                            public void onDrawerClosed(View drawerView)
                            {
                                super.onDrawerClosed(drawerView);

                            }
                        });
                drawer.closeDrawer(navList);
            }
        });

    }

EDIT:I’m adding a bounty on this, as this is a very old issue that exists even today with the latest Android-X (sample available here). Here’s how it looks:

enter image description here

I’ve reported about it to Google (here and later again here), but it didn’t help.

I’ve tried all existing solutions here on this thread, and none worked. If anyone has a good workaround for this (while still using DrawerLayout or extending it, or something similar), please put a working solution.

How to&Answers:

Note that you can get around this 20dp peek feature by setting the clickable attribute to true on the FrameLayout within the DrawerLayout.

android:clickable=”true”

for instance :
http://developer.android.com/training/implementing-navigation/nav-drawer.html

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clickable="true" />
    <!-- The navigation drawer -->
    <ListView
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#111"
        android:choiceMode="singleChoice"
        android:divider="@android:color/darker_gray"
        android:dividerHeight="1dp" />
</android.support.v4.widget.DrawerLayout>

Answer:

If you had shown us your layout xml, we could see if you have DrawerLayout as ROOT element. And whether the inside two children are Main Layout and Navigation Drawer.

According to Create a Drawer Layout:

To add a navigation drawer, declare your user interface with a DrawerLayout object as the root view of your layout. Inside the DrawerLayout, add one view that contains the main content for the screen (your primary layout when the drawer is hidden) and another view that contains the contents of the navigation drawer.

Answer:

I’ve managed to work around this by implementing this DrawerListener:

drawerLayout.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
            @Override
            public void onDrawerStateChanged(int newState) {
                super.onDrawerStateChanged(newState);
                if (drawerLayout.isDrawerVisible(Gravity.LEFT) && !drawerLayout.isDrawerOpen(Gravity.LEFT)) {
                    drawerLayout.closeDrawer(Gravity.LEFT);
                }
            }
        });

Whenever the state changes, if the drawer is visible but not open, it means it’s ‘peeking’, so I close it.

Answer:

This 20dp Peek feature can be achieved When user drags the drawer to 20dp than open the drawer.
Here is code working fine for me.

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {


lateinit var mToggle: ActionBarDrawerToggle
lateinit var mDrawerLayout: DrawerLayout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val toolbar: Toolbar = findViewById(R.id.toolbar)
    setSupportActionBar(toolbar)

    val fab: FloatingActionButton = findViewById(R.id.fab)
    fab.setOnClickListener { view ->
        Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
            .setAction("Action", null).show()
    }

    mDrawerLayout = findViewById(R.id.drawer_layout)
    val navView: NavigationView = findViewById(R.id.nav_view)

    mToggle = ActionBarDrawerToggle(
        this, mDrawerLayout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close
    )
    mDrawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
        override fun onDrawerStateChanged(newState: Int) {
            Log.d("onDrawerStateChanged", "$newState")
            mToggle.onDrawerStateChanged(newState)
        }

        override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
            if ((slideOffset >= (dpToPx(19.9f)/drawerView.width)) && (slideOffset <= (dpToPx(20.1f)/drawerView.width))){
                Log.d("onDrawerSlide", "true")
                mDrawerLayout.openDrawer(GravityCompat.START)
            }
            Log.d("onDrawerSlide", "$slideOffset")
            mToggle.onDrawerSlide(drawerView,slideOffset)
        }

        override fun onDrawerClosed(drawerView: View) {
            mToggle.onDrawerClosed(drawerView)
        }

        override fun onDrawerOpened(drawerView: View) {
            mToggle.onDrawerOpened(drawerView)
        }

    })

    mToggle.syncState()

    navView.setNavigationItemSelectedListener(this)
}

override fun onBackPressed() {
    val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
    if (drawerLayout.isDrawerOpen(GravityCompat.START)) {
        drawerLayout.closeDrawer(GravityCompat.START)
    } else {
        super.onBackPressed()
    }
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    // Inflate the menu; this adds items to the action bar if it is present.
    menuInflater.inflate(R.menu.main, menu)
    return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    return when (item.itemId) {
        R.id.action_settings -> true
        else -> super.onOptionsItemSelected(item)
    }
}

override fun onNavigationItemSelected(item: MenuItem): Boolean {
    // Handle navigation view item clicks here.
    when (item.itemId) {
        R.id.nav_home -> {
            // Handle the camera action
        }
        R.id.nav_gallery -> {

        }
        R.id.nav_slideshow -> {

        }
        R.id.nav_tools -> {

        }
        R.id.nav_share -> {

        }
        R.id.nav_send -> {

        }
    }
    val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
    drawerLayout.closeDrawer(GravityCompat.START)
    return true
}

fun dpToPx(dps : Float) : Float{
    return (dps * Resources.getSystem().displayMetrics.density)
}

}