Question

I started writing an app for Android. I have a problem with the Animation of the NavigationDrawer icon at the top left. It works correctly when the application is launched for the first time but when I pick an item from the list in the NavgationDrawer its icon stays in the "open" state even though the `NavigationDrawer closes as it should.

Here is my MainActivity:

import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.app.ActionBar;
import android.os.Bundle;
import android.app.Activity;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.content.res.*;

public class MainActivity extends FragmentActivity {

    ActionBarDrawerToggle icon;
    final String[] listContent ={"Accueil","Fiche technique","Pilotes","Ecuries"};
    final String[] fragments ={
            "com.mycompany.f1holo.MainPageFragment",
            "com.mycompany.f1holo.FirstFragment",
            "com.mycompany.f1holo.SecondFragment",
            "com.mycompany.f1holo.ThirdFragment"};

    private ActionBarDrawerToggle actionBarDrawerToggle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ArrayAdapter<String> ad = new ArrayAdapter<String>(getActionBar().getThemedContext(), android.R.layout.simple_list_item_1, listContent);

        final DrawerLayout drawer = (DrawerLayout)findViewById(R.id.drawer_layout);
        final ListView list = (ListView) findViewById(R.id.drawer);

        actionBarDrawerToggle = new ActionBarDrawerToggle(
                this,
                drawer,
                R.drawable.navdrawer,
                R.string.open,
                R.string.close);

        drawer.setDrawerListener(actionBarDrawerToggle);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        list.setAdapter(ad);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, final int position, long id) {
                drawer.setDrawerListener( new DrawerLayout.SimpleDrawerListener(){

                    @Override
                    public void onDrawerClosed(View drawerView){
                        super.onDrawerClosed(drawerView);
                        FragmentTransaction transition = getSupportFragmentManager().beginTransaction();
                        transition.replace(R.id.mains, Fragment.instantiate(MainActivity.this, fragments[position]));
                        transition.commit();
                    }
                });
                drawer.closeDrawer(list);
            }
        });
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);

        actionBarDrawerToggle.syncState();
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (actionBarDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        switch (item.getItemId())
        {
            case R.id.mainMenuAbout:
                Toast.makeText(this, "F1 Holo", Toast.LENGTH_SHORT).show();
                return true;
            case R.id.mainMenuQuitter:
                finish();
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {    
        getMenuInflater().inflate(R.menu.main_menu, menu);
        getMenuInflater().inflate(R.menu.main_about, menu);
        return true;    
    }
}

And here is my FirstFragment:

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class FirstFragment extends Fragment {

    public static Fragment newInstance(Context context) {
        FirstFragment frag = new FirstFragment();
        return frag;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle   savedInstanceState) {
        ViewGroup root = (ViewGroup) inflater.inflate(R.layout.first_fragment_layout,  null);
        return root;
    }
}
Was it helpful?

Solution

I have found the solution and it is so obvious I could kick myself for not noticing before...

The problem is here:

list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView parent, View view, final int position, long id) {
        drawer.setDrawerListener( new DrawerLayout.SimpleDrawerListener() {

            @Override
            public void onDrawerClosed(View drawerView) {
                super.onDrawerClosed(drawerView);
                FragmentTransaction transition = getSupportFragmentManager().beginTransaction();
                transition.replace(R.id.mains, Fragment.instantiate(MainActivity.this, fragments[position]));
                transition.commit();
            }
        });
        drawer.closeDrawer(list);
    }
});

In this OnClickListener you are setting a new SimpleDrawerListener and therefore overriding this line:

drawer.setDrawerListener(actionBarDrawerToggle);

This disconnects the ActionBarDrawerToogle from the DrawerLayout and as a result stops the animations from playing... This is all you need:

list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView parent, View view, final int position, long id) {
        FragmentTransaction transition = getSupportFragmentManager().beginTransaction();
        transition.replace(R.id.mains, Fragment.instantiate(MainActivity.this, fragments[position]));
        transition.commit();

        drawer.closeDrawer(list);
    }
});

Why would you want to do this anyway? It just causes a delay between the user picking the item and the content actually changing. If it is because of performance issues - maybe that the close animation of the NavigationDrawer is not playing correctly - then doing something like this might be appropriate but in any case if you decide to implement this do it like this:

First create global variable called drawerItemSelection:

private String drawerItemSelection = null;

And then implement your ItemClickListener like this:

list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView parent, View view, final int position, long id) {
        drawerItemSelection = fragments[position];

        drawer.closeDrawer(list);
    }
});

And finally in your onCreate() method implement the ActionBarDrawerToogle like this:

actionBarDrawerToggle = new ActionBarDrawerToggle(this, drawer, R.drawable.navdrawer, R.string.open, R.string.close) {

    @Override
    public void onDrawerClosed(View drawerView) {
        super.onDrawerClosed(drawerView);

        if(drawerItemSelection != null) {
            FragmentTransaction transition = getSupportFragmentManager().beginTransaction();
            transition.replace(R.id.mains, Fragment.instantiate(MainActivity.this, drawerItemSelection));
            transition.commit();

            drawerItemSelection = null;
        }
    }
};

If you have any further questions feel free to ask!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top