collin
collin

Reputation: 297

Open next activity only after navigation drawer completes it closing animation

I'm using Navigation Drawer in my application.

When the user clicks on any of the menu item in drawer, it opens a new Activity (not fragment).

Now, I'm using slide_right_in/slide_left_out animation as transition between activities.

The code works, but these animations conflicts with the closing animation of Navigation Drawer, as even before the drawer gets completely closed, the current activity starts sliding out to left & next activity starts sliding in from right.

So, is there any way to start the animation only after drawer is completely closed?

Thank You

Upvotes: 10

Views: 8914

Answers (7)

sHaRkBoY
sHaRkBoY

Reputation: 571

Every answer is so complicated..... It's so easy.

Just add a drawerlistener and do something in onClosed() method:

DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

when you select a item from navigation drawer you will call this method to close the drawer:

drawer.closeDrawer(GravityCompat.START);

after the above method call just add below lines and do whatever you want:

drawer.addDrawerListener(new DrawerLayout.DrawerListener() {
        @Override
        public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {

        }

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

        }

        @Override
        public void onDrawerClosed(@NonNull View drawerView) {
            startActivity(finalIntent);

           // Or else do something here....
        }

        @Override
        public void onDrawerStateChanged(int newState) {

        }
    });

Upvotes: 3

Vivek Barai
Vivek Barai

Reputation: 1358

I have found a simple way to get rid of id you may try this and its working and tested.

OLD ANSWER:

int id = -1;
 @Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    id = item.getItemId();        

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    drawer.closeDrawer(GravityCompat.START);

    drawer.setDrawerListener(new DrawerLayout.DrawerListener() {
        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
        }

        @Override
        public void onDrawerOpened(View drawerView) {
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            if (id == R.id.NAV_YOUR_ACTIVITY_ONE) {
                Intent activityIntent = new Intent(getApplicationContext(), YOUR_ACTIVITY_ONE.class);
                activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(activityIntent);
            }
            else if (id == R.id.NAV_YOUR_ACTIVITY_TWO) {
                Intent activityIntent = new Intent(getApplicationContext(), YOUR_ACTIVITY_TWO.class);
                activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(activityIntent);
            }

            //do not forget to set id again to -1 or else it will cause problem
            id=-1;
        }

        @Override
        public void onDrawerStateChanged(int newState) {
        }
    }
}

UPDATE ANSWER:

You can your ActionBarDrawerToggle too for example observe below code.

int id = -1;

//Use this function for click effect be performed on drawer item clicked
public void perfromDrawerNavigation(){
    if (id == R.id.NAV_YOUR_ACTIVITY_ONE) {
            Intent activityIntent = new Intent(getApplicationContext(), YOUR_ACTIVITY_ONE.class);
            activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(activityIntent);
        }
        else if (id == R.id.NAV_YOUR_ACTIVITY_TWO) {
            Intent activityIntent = new Intent(getApplicationContext(), YOUR_ACTIVITY_TWO.class);
            activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(activityIntent);
        }

        //do not forget to set id again to -1 or else it will cause problem
        id=-1;
}

//you can write this code in onCreate() also
public void initControl(){
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    getSupportActionBar().setTitle(
         getResources().getString(R.string.activity));
    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close){
        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);
            if(id != -1){
               perfromDrawerNavigation();
            }
        }
    };
    drawer.addDrawerListener(toggle);
    toggle.setDrawerIndicatorEnabled(true);
    toggle.syncState();
}

@Override
public boolean onNavigationItemSelected(MenuItem item) {
    // Handle navigation view item clicks here.
    id = item.getItemId();
    drawer.closeDrawer(GravityCompat.START);
}

Upvotes: 0

Mariusz
Mariusz

Reputation: 508

I did this somehow similiar to Jan.

Select an item

If an item gets clicked, i save its id and close the Drawer:

navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
    {
        @Override
        public boolean onNavigationItemSelected(MenuItem menuItem)
        {
            clickedItem = menuItem.getItemId();
            drawerLayout.closeDrawers();
            return true;
        }
    });

Listen for drawer close

If the Drawer gets closed i listen for it and check if an item has been clicked. If it has i call my method to handle the navigation click.

drawerToggle = new ActionBarDrawerToggle(activity, drawerLayout, R.string.accessibility_open_nav, R.string.accessibility_open_nav)
    {
        @Override
        public void onDrawerClosed(View drawerView)
        {
            super.onDrawerClosed(drawerView);

            if(clickedItem != 0)
            {
                handleNavigationClick();
            }
        }
    };

drawerLayout.setDrawerListener(drawerToggle);

Handle the click

Here i react to the item click on open intents in this case (simplified). You need to reset the clickedItem here to 0. That is, because if you go back to an activity, open and close the drawer, it would still have the clickedItem number and would handle the click again.

private void handleItemClick()
{
    switch (clickedItem)
    {
        case R.id.item_1:
            do_something_1;
            break;

        case R.id.item_2:
            do_something_2;
            break;
    }

    clickedItem = 0;
}

Upvotes: 6

Jan Lněnička
Jan Lněnička

Reputation: 11

I extend all my activities where I want to have a Navigation drawer by DrawerActivity class. Because I had a little animation conflict as well so I start my Activities after Navigation drawer is completely closed. This is implementation which covers all cases:

public class DrawerActivity extends AppCompatActivity {
  private String[] mMenuTitles;
  private DrawerLayout mDrawerLayout;
  private ListView mDrawerList;
  private CharSequence mTitle;
  private ActionBarDrawerToggle mDrawerToggle;

  private Boolean isItemClicked = false;

  protected void onCreateDrawer() {


    mTitle = getResources().getString(R.string.app_name);
    mMenuTitles = new String[]{getString(R.string.drawer_item1), getString(R.string.drawer_item2), getString(R.string.drawer_item3)};
    mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    mDrawerLayout.setScrimColor(getResources().getColor(R.color.black_transparent_30));
    // mDrawerLayout.setScrimColor(Color.TRANSPARENT);
    mDrawerList = (ListView) findViewById(R.id.left_drawer);

    // Set the adapter for the list view
    mDrawerList.setAdapter(new ArrayAdapter<String>(this,
            R.layout.drawer_list_item, mMenuTitles));
    // Set the list's click listener
    mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

    mDrawerToggle = new ActionBarDrawerToggle(
            this,                  /* host Activity */
            mDrawerLayout,         /* DrawerLayout object */
            // R.mipmap.ic_drawer,  /* nav drawer icon to replace 'Up' caret   */
            R.string.drawer_open,  /* "open drawer" description */
            R.string.drawer_close  /* "close drawer" description */
    ) {

If item is clicked, I start activity on checked position.

        /** Called when a drawer has settled in a completely closed state.     */
        public void onDrawerClosed(View view) {
            if (isItemClicked) {
                int position = mDrawerList.getCheckedItemPosition();
                startMyActivity(position); 
                isItemClicked = false;
            }

Method setCheckedItem is overriden in extended activities for showing checked item consistently.

            setCheckedItem(mDrawerList);
            //  getSupportActionBar().setTitle(mTitle);
        }

        /** Called when a drawer has settled in a completely open state. */
        public void onDrawerOpened(View drawerView) {
            //  getSupportActionBar().setTitle(mTitle);
        }
    };

    // Set the drawer toggle as the DrawerListener
    mDrawerLayout.setDrawerListener(mDrawerToggle);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);
}

public void setCheckedItem(ListView mDrawerList) {
}

@Override
protected void onPostCreate(Bundle savedInstanceState) {
    super.onPostCreate(savedInstanceState);
    setCheckedItem(mDrawerList);
    // Sync the toggle state after onRestoreInstanceState has occurred.
    mDrawerToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    mDrawerToggle.onConfigurationChanged(newConfig);
}

private void selectItem(int position) {
    mDrawerList.setItemChecked(position, true);
    // setTitle(mMenuTitles[position]);
    // Toast.makeText(this, mTitle, Toast.LENGTH_SHORT).show();

    // startMyActivity(position);
    mDrawerLayout.closeDrawer(mDrawerList);
}

public void startMyActivity(int position) {
//is overriden in extended activities for being able to send data to another activity
}

private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override

Item is clicked so I set my helper atribute to true.

    public void onItemClick(AdapterView parent, View view, int position, long id) {
        isItemClicked = true;
        selectItem(position);
    }
}

public void setTitle(CharSequence title) {
    mTitle = title;
    getSupportActionBar().setTitle(mTitle);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // 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.
    int id = item.getItemId();
    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }
    // Pass the event to ActionBarDrawerToggle, if it returns
    // true, then it has handled the app icon touch event
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }
    return super.onOptionsItemSelected(item);
}}

Upvotes: 0

Denis Nek
Denis Nek

Reputation: 1884

The nikis's answer does not cover all cases. If your Fragment or Activity contains map or CameraView it may costs more time. And differences between simple screen and screen with map too big so it's hard to select a good delay.

The best approach is to send callback to NavigationDrawer from just opened Activity/Fragment in onResume(). Then close drawer in this callback.

Upvotes: 0

MSr
MSr

Reputation: 288

Don't close navigation drawer. It will slide with the old activity. Or call startActivity after drawerLayout.closeDrawer(drawerList);

public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    drawerLayout.closeDrawer(drawerList);
    Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
    //set animation here
    startActivity(intent);
    finish();
}

Upvotes: 1

nikis
nikis

Reputation: 11234

You can open Activity with a delay. For example, in such a way Activity will be started after 250ms:

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        Intent intent = new Intent(<filter>);
        startActivity(intent);
        finish();
    }
}, 250);
mDrawerLayout.closeDrawer(mDrawerList);

Upvotes: 11

Related Questions