Gábor
Gábor

Reputation: 10224

Event before DrawerLayout opens

It seems to me that one thing is missing from the DrawerLayout implementation: and event that fires before the drawer opens.

drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
  public void onDrawerClosed(View view) {
    //...
  }

  public void onBeforeDrawerOpened(View drawerView) {
    //...
  }

  public void onDrawerOpened(View drawerView) {
    //...
  }
};

The reason for needing it would be to set up the status of the drawer items like menu items selected, enabled and similar. Putting this into the onDrawerOpened() callback kinda works but it doesn't look really right to change the menu appearance after it opens.

My first thought would be to extend ActionBarDrawerToggle and provide the new event. Shall I re-invent the wheel :-) or has this already been done by somebody?

Upvotes: 5

Views: 4008

Answers (4)

Code on the Rocks
Code on the Rocks

Reputation: 17576

The setDrawerListener method recommended in the accepted answer is now deprecated. The new way to do this is to use the addDrawerListener method.

In Kotlin:

  1. Initialize the DrawerLayout View

    val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)

  2. In your main activity, create an inner class that is a subclass of DrawerLayout.DrawerListener. The DrawerLayout class implements the DrawerListener interface. You can track the changing drawer position in onDrawerSlide and determine if the drawer is opening or closing:

    inner class CustomDrawer : DrawerLayout.DrawerListener{
      override fun onDrawerStateChanged(newState: Int) {
      }
    
    var last: Float = 0f
    
    override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
        imm.hideSoftInputFromWindow(drawerView?.getWindowToken(), 0)
    
        var opening: Boolean = slideOffset>last
        var closing: Boolean = slideOffset<last
    
        if(opening) {
            Log.i("Drawer","opening")
            Log.d("Last",last.toString())
        } else if(closing) {
            Log.i("Drawer","closing")
            Log.d("Last",last.toString())
        } else {
            Log.i("Drawer","doing nothing")
            Log.d("Last",last.toString())
        }
    }
    
    override fun onDrawerClosed(drawerView: View) {
    
      }
    
    override fun onDrawerOpened(drawerView: View) {
    
      }
    }
    
  3. Add your custom DrawerListener to the drawerLayout (I put it in the onCreate method)

    var drawerListener = CustomDrawer()
    drawerLayout.addDrawerListener(drawerListener)
    

Upvotes: 0

peterzinho16
peterzinho16

Reputation: 989

Mix of from Lenny and Fred answers for kotlin:

    var toggle = object : ActionBarDrawerToggle(this,
    drawer_layout, toolbar, R.string.drawer_open, R.string.drawer_close) {

        override fun onDrawerStateChanged(newState: Int) {
            super.onDrawerStateChanged(newState)

            if(newState == DrawerLayout.STATE_SETTLING){
                if(drawer_layout.isDrawerOpen(Gravity.LEFT)){
                    //closing
                }else{
                    //opening
                }
            }
        }
    }
    drawer_layout.addDrawerListener(toggle)
    toggle.syncState()

Upvotes: 0

Fred
Fred

Reputation: 3421

This link can help you to solve your problem. How to detect that the DrawerLayout started opening?

Use onDrawerStateChanged(int newState) callback

You need to listen to STATE_SETTLING states - this state is reported whenever drawer starts moving (either opens or closes). So once you see this state - check whether drawer is opened now and act accordingly:

    mDrawerToggle = new ActionBarDrawerToggle(
        this,                 
        mDrawerLayout,        
        R.drawable.ic_drawer,  
        R.string.drawer_open,  
        R.string.drawer_close  
) {
    @Override
    public void onDrawerStateChanged(int newState) {
        if (newState == DrawerLayout.STATE_SETTLING) {
            if (!isDrawerOpen()) {
                // starts opening
                getActionBar()
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            } else {
                // closing drawer
                getActionBar()
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            }
            invalidateOptionsMenu();
        }
    }
};
mDrawerLayout.setDrawerListener(mDrawerToggle);

Upvotes: 8

Lenny
Lenny

Reputation: 5939

I found this on google when I came up against this problem and didn't find an exact answer anywhere so I decided I'd post the complete answer. Hopefully it will save someone some time.

The best solution I found was to monitor the drawer state and determine if it's opening or closing using the isDrawerOpen method. Be sure to set the gravity to match the gravity used in opening / closing your drawer.

DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// ...
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
R.drawable.ic_playlist, R.string.drawer_open, R.string.drawer_close) {
    public void onDrawerStateChanged(int newState) {
        if(newState == DrawerLayout.STATE_DRAGGING){
            if(mDrawerLayout.isDrawerOpen(Gravity.LEFT)){
                //closing

            }else{
                //opening

            }
        }
    }
}

Upvotes: 3

Related Questions