25

I am using this example for navigation drawer. When clicking on of item of left drawer listview it shows some images but drawerLayout closes not smoothly.

What should I do here for smoothly close left drawer layout after clicking of the item of listview.

fish40
  • 5,738
  • 17
  • 50
  • 69
  • http://www.curious-creature.org/2012/12/01/android-performance-case-study/ – CommonsWare Sep 18 '13 at 12:03
  • 1
    @CommonsWare thank you for your answer but what should I find here? – fish40 Sep 18 '13 at 12:08
  • You will find a blog post by Romain Guy that describes tools and techniques for identifying the source of jank in your app. – CommonsWare Sep 18 '13 at 12:09
  • search before you ask: http://stackoverflow.com/questions/11377472/navigation-drawer-google-vs-youtube – agamov Sep 18 '13 at 12:10
  • 2
    @agamov thanks for your support but I'm noy saying how to create navigation drawer, I mean SMOOTH navigation drawer. – fish40 Sep 18 '13 at 12:12
  • I also tried NavigationDrawer from support library, but it was not smooth even on empty project. I'm using SlidingMenu instead, it's quite smooth. – agamov Sep 18 '13 at 12:17
  • @agamov I read this post that's why choose navigation drawer http://stackoverflow.com/questions/16810896/what-is-the-difference-between-the-slidingmenu-library-and-the-android-navigatio – fish40 Sep 18 '13 at 12:22
  • Show your code! "What should I do here" -- Where?! – Paul Burke Sep 18 '13 at 12:28
  • I just use developer.android example (there is a link above that i provide) – fish40 Sep 18 '13 at 12:33
  • @fish40 You did not change the code **at all**? – Paul Burke Sep 18 '13 at 12:36
  • I try to find some solutions, but nothing. But this example (not changing nothing) also not working smoothly in my phone. – fish40 Sep 18 '13 at 12:38

5 Answers5

64

Not sure this is the best route, but the way I solved this was to create a pending Runnable that runs in onDrawerClosed. Eg:

private void selectItem(final int position) {
    mPendingRunnable = new Runnable() {
        @Override
        public void run() {
            // update the main content by replacing fragments
            Fragment fragment = new PlanetFragment();
            Bundle args = new Bundle();
            args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
            fragment.setArguments(args); 

            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
        }
    });

    // update selected item and title, then close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(mPlanetTitles[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

@Override
public void onDrawerClosed(View view) {
    getActionBar().setTitle(mTitle);
    invalidateOptionsMenu();

    // If mPendingRunnable is not null, then add to the message queue 
    if (mPendingRunnable != null) {
        mHandler.post(mPendingRunnable);
        mPendingRunnable = null;
    }
}
shaktiman_droid
  • 2,368
  • 1
  • 17
  • 32
Paul Burke
  • 25,496
  • 9
  • 66
  • 62
  • 1
    can I ask, where do you get mHandler from? I'm trying to do this in C#, but am hung up on where it's coming from. – Chase Florell May 07 '14 at 18:18
  • 3
    @ChaseFlorell Simply create a member variable. E.g. `Handler mHandler = new Handler();` – Paul Burke May 07 '14 at 18:24
  • 5
    I'd like to add: since `onDrawerClosed()` is not called upon starting your app, you should also post `mPendingRunnable` to `mHandler` at the end of `onCreate()`. – nucleartide May 27 '14 at 20:21
  • You can do all actions from `selectItem` in `onDrawerClosed`. The latest version of Gmail do it in such way. – Artem Mostyaev Feb 16 '15 at 09:13
  • 1
    Don't forget to implement `DrawerLayout.DraweListener` in the Activity and set the listener: `drawer.setDrawerListener(this);` – Nil Llisterri Oct 03 '17 at 09:48
13

Works perfect

private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
            mDrawerLayout.closeDrawer(mDrawerList);
            mDrawerLayout.postDelayed(new Runnable() {
                @Override
                public void run() {
                    selectItem(position);
                }
            }, 300);
        }
    }
Georgy Gobozov
  • 13,633
  • 8
  • 72
  • 78
1

Just posting the drawerLayout.closeDrawer() on the message queue using the handler, with a minimal delay solved my problem. Handler.postDelayed() is the key here.

 public void selectItem(int position)
    {
        switch (position)
        {
            case 0:

                DashboardFragment dashboardFragment = new DashboardFragment();
                Bundle args = new Bundle();
                args.putInt(dashboardFragment.ARG_SCREEN_NUMBER, position);
                dashboardFragment.setArguments(args);

                FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

                // Replace whatever is in the fragment_container view with this fragment,
                // and add the transaction to the back stack so the user can navigate back
                transaction.replace(R.id.fragmentLayout, dashboardFragment, TAG_DASHBOARD);
                transaction.addToBackStack(null);

                // Commit the transaction
                transaction.commit();
                getSupportFragmentManager().executePendingTransactions();
                break;            

            default:
                break;

        }

        // Highlight the selected item, update the title, and close the drawer
        drawerList.setItemChecked(position, true);
        setTitle(mScreenTitles[position]);

        mPendingRunnable = new Runnable()
        {
            @Override
            public void run()
            {
                drawerLayout.closeDrawer(GravityCompat.START);
            }
        };
        mHandler.postDelayed(mPendingRunnable,50);

    }
Ajit
  • 964
  • 10
  • 17
0

I don't use threads, because i need to update UI after close the navigation menu.

Following code works for me.

i am using fragment as member variable of class to update ui

setFragment() function use to assign fragment to fragment variable

In onDrawerClosed() event, i update ui.

mDrawerList.setOnItemClickListener(new ListView.OnItemClickListener()
{
   @Override
   public void onItemClick(AdapterView<?> parent, View view, int position, long id)
   {
       setFragment(position);
   }
});


// for getting fragment
protected void setFragment(int p)
{
    fragment = null;

    switch (position)
    {
        case 1:
            fragment = new DashboardFragment();                
            break;
    }

    if (fragment != null)
    {
        mDrawerList.setItemChecked(position, true);
        mDrawerList.setSelection(p);
        mDrawerLayout.closeDrawer(mDrawerList);
    }
}


// on close draw , fragment is loaded on screen
public void onDrawerClosed(View view)
{
   getSupportActionBar().setTitle(mTitle);
   invalidateOptionsMenu();

   FragmentManager fragmentManager = getSupportFragmentManager();

   fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
}
Hardeep Singh
  • 743
  • 1
  • 8
  • 18
0

Please review my MainActivity to make smooth DrawerLayout (open/close) with a custom topBar layout.

public class MainActivity extends BaseActivity
    implements NavigationView.OnNavigationItemSelectedListener {

Fragment fragment = null;
Class fragmentClass = null;
FrameLayout frameLayout;
TextView topTilte;
DrawerLayout drawer;
NavigationView navigationView;
private boolean isDrawerOpen = false;

@Override
protected void onCreateFinished() {
    setContentView(R.layout.activity_main);

    drawer = findViewById(R.id.drawer_layout);
    navigationView = findViewById(R.id.nav_view);

    topTilte = findViewById(R.id.toolbar_title);
    fragmentClass = HomeFragment.class;
    topTilte.setText(R.string.menu_home);
    setFragment();

    drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
        @Override
        public void onDrawerSlide(@NonNull View view, float slideOffset) {
            if(slideOffset > .55 && !isDrawerOpen){
                onDrawerOpened(view);
                isDrawerOpen = true;
            } else if(slideOffset < .45 && isDrawerOpen) {
                onDrawerClosed(view);
                isDrawerOpen = false;
            }
        }

        @Override
        public void onDrawerOpened(@NonNull View view) {

        }

        @Override
        public void onDrawerClosed(@NonNull View view) {

        }

        @Override
        public void onDrawerStateChanged(int i) {

        }
    });

    navigationView.setNavigationItemSelectedListener(this);
}

@Override
protected void afterInjection() {

}

public void openMenu(View v) {
    drawer.openDrawer(Gravity.LEFT);
}

@Override
public void onBackPressed() {
    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    if (drawer.isDrawerOpen(GravityCompat.START)) {
        drawer.closeDrawer(GravityCompat.START);
    } else {
        super.onBackPressed();
    }
}

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    int id = item.getItemId();
    if (id == R.id.nav_home) {
        topTilte.setText(R.string.menu_home);
        fragmentClass = HomeFragment.class;
        setFragment();

    } else if (id == R.id.nav_profile) {

    } 

    return true;
}

private void setFragment() {


    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            try {
                fragment = (Fragment) fragmentClass.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }

            FragmentManager fragmentManager = getSupportFragmentManager();
            fragmentManager.beginTransaction().replace(R.id.container, fragment).commit();

            drawer.closeDrawer(GravityCompat.START);
        }
    }, 200);
}
}
idris yıldız
  • 2,097
  • 20
  • 22