DrawerLayout getting stuck on swipe

空扰寡人 提交于 2019-11-29 23:48:57

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>
Wenza

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.

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.

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)
}

}

Update

The is hosted opensource on github.

To use you simply need to import it in graddle. (it wasn't working sometime before, i guess because jitpack may need some time)

dependencies {
   implementation 'com.github.mayank1513:SP_DrawerLayout:master-SNAPSHOT'

Make sure you also add maven { url 'https://jitpack.io' } in your project level graddle file.

The final step and you are ready to add your drawer

add custom xmlns. You can do this by adding this line to your root view

xmlns:custom="http://schemas.android.com/apk/res-auto"

Now Create your drawer - you are in complete control what you want to put inside

<com.mayank.drawerlayout.Drawer 
  android:id="@+id/drawer"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="@color/colorPrimary"

  custom:drawerBackground="@color/colorAccent"
  custom:drawerWidth="250dp"
  custom:onRightEdge="false">
  <!--Create what you want to put inside your drawer here-->
</com.mayank.drawerlayout.Drawer> 

Note:

  • The concern raised in comments that it opens on slight touch is resolved.
  • reduced drag tolerance for closing the drawer.

Original Answer

You can use Custom DrawerLayout Class. Please find source code and details here.

This class features both left as well as right side DrawerLayout and if pretty simple to use and customize without significant changes to java code.

I have used this in my apps this, this and this. Just in case you want to try it before using.

Best wishes.

Edit I have put the code in app and module format here - https://github.com/mayank1513/SP_DrawerLayout .

Now Custom attributes are used for setting left or right edge, background and drawer width. You can simple add this inside your XML layout. You can either create drawer inside a dedicated frame layout and set initial alpha to 0 or add a line to add shadowing background - you can find this in the demo app.

You can create lists, scrollView etc. inside this drawerLayout.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!