Impossible d'attraper l'événement de clic sur le bouton d'accueil de la barre d'outils


106

J'ai implémenté la dernière bibliothèque appcompat et j'utilise la Toolbarbarre d'action as. Mais le problème est que je ne peux pas attraper l'événement de clic sur le bouton d'accueil / l'icône du hamburger. J'ai tout essayé et tout regardé mais je ne semble pas trouver de problème similaire.

Voici ma Activityclasse:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    // Set up the drawer.
    navDrawerFragment = 
        (NavigationDrawerFragment) getSupportFragmentManager()
        .findFragmentById(R.id.navigation_drawer);
    navDrawerFragment.setUp(
        R.id.navigation_drawer, 
        (DrawerLayout) findViewById(R.id.drawer_layout), 
        toolbar);
}

Et voici ma classe NavigationDrawerFragment:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState != null) {
        currentSelectedPosition = savedInstanceState.getInt(
            STATE_SELECTED_POSITION);
        fromSavedInstanceState = true;
    }

    // Select either the default item (0) or the last selected item.
    selectItem(currentSelectedPosition);
}

@Override
public void onActivityCreated (Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Indicate that this fragment would like 
    // to influence the set of actions in the action bar.
    setHasOptionsMenu(true);
}

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        drawerListView = (ListView) inflater.inflate(
            R.layout.fragment_navigation_drawer, container, false);
        drawerListView.setOnItemClickListener(
            new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, 
                View view, int position, long id) {
                selectItem(position);
            }
        });
        //mDrawerListView.setAdapter();
        //mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
        return drawerListView;
}

public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
    fragmentContainerView = getActivity().findViewById(fragmentId);
    this.drawerLayout = drawerLayout;

    // set a custom shadow that overlays the main 
    // content when the drawer opens
    drawerLayout.setDrawerShadow(
        R.drawable.drawer_shadow, GravityCompat.START);
    // set up the drawer's list view 
    // with items and click listener

    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeButtonEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the navigation drawer and the action bar app icon.
    drawerToggle = new ActionBarDrawerToggle(
        getActivity(), 
        drawerLayout, 
        toolbar, 
        R.string.navigation_drawer_open, 
        R.string.navigation_drawer_close) {
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
        }

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

    // If the user hasn't 'learned' about the drawer, 
    // open it to introduce them to the drawer,
    // per the navigation drawer design guidelines.
    if (!userLearnedDrawer && !fromSavedInstanceState) {
        drawerLayout.openDrawer(fragmentContainerView);
    }

    // Defer code dependent on restoration of previous instance state.
    drawerLayout.post(new Runnable() {
        @Override
        public void run() {
            drawerToggle.syncState();
        }
    });

    drawerLayout.setDrawerListener(drawerToggle);
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // Forward the new configuration the drawer toggle component.
    drawerToggle.onConfigurationChanged(newConfig);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d("cek", "item selected");
    if (drawerToggle.onOptionsItemSelected(item)) {
        Log.d("cek", "home selected");
        return true;
    }

    return super.onOptionsItemSelected(item);
}

lorsque j'ai cliqué sur un élément de menu, le journal "élément sélectionné" est appelé. Mais lorsque je clique sur le bouton d'accueil, cela ouvre le tiroir de navigation mais le journal "accueil sélectionné" n'est jamais appelé. J'ai également défini la onOptionsItemSelectedméthode dans mon Activity, mais elle n'est toujours pas appelée.

Réponses:


224

Si vous voulez savoir à quel moment l'utilisateur clique sur la maison, AppCompatActivityvous devriez l'essayer comme ceci:

Dites d'abord à Android que vous souhaitez utiliser votre Toolbarcomme votre ActionBar:

setSupportActionBar(toolbar);

Ensuite, définissez Accueil pour qu'il s'affiche setDisplayShowHomeEnabledcomme ceci:

getSupportActionBar().setDisplayShowHomeEnabled(true);

Enfin, écoutez les événements de clic android.R.id.homecomme d'habitude:

@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
    if (menuItem.getItemId() == android.R.id.home) {
        Timber.d("Home pressed");
    }
    return super.onOptionsItemSelected(menuItem);
}

Si vous voulez savoir quand le bouton de navigation est cliqué sur un Toolbardans une classe autre que AppCompatActivityvous pouvez utiliser ces méthodes pour définir une icône de navigation et écouter les événements de clic dessus. L'icône de navigation apparaîtra sur le côté gauche de votre Toolbaremplacement où se trouvait le bouton "Accueil".

toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("cek", "home selected");
    }
});

Si vous voulez savoir quand le hamburger est cliqué et quand le tiroir s'ouvre, vous écoutez déjà ces événements via onDrawerOpenedet onDrawerClosedvous voudrez donc voir si ces rappels correspondent à vos besoins.


1
J'ai essayé la première partie avant, mais cela ne fonctionne pas. J'ai essayé la deuxième partie, et ça marche. Mais l'icône ne change pas si j'enregistre la barre d'outils avec le tiroir de navigation. Une autre question, y a-t-il un remplacement pour setDrawerIndicatorEnabled pour cela? J'ai essayé avec ce nouveau tiroir de navigation et j'ai obtenu une erreur. Merci
Dark Leonhart

La deuxième solution fonctionne. Mais comment pouvons-nous détecter le bouton d'accueil cliqué et le bouton du tiroir dans la deuxième solution. Lorsque je clique sur l'icône du tiroir, cela n'ouvre pas le tiroir.
Dory

2
Lorsque vous définissezNavigationOnClickListener pour la barre d'outils, vous perdez le comportement du tiroir "natif" :(
IlyaEremin

7
Alors maintenant, nous avons besoin d'un écouteur de clic séparé alors qu'avant, dans les fragments, nous pouvions vérifier android.R.id.home dans onOptionsItemSelected ()? C'est vraiment très ennuyeux
Daniel Wilson

1
re: Toolbar, si vous définissez un nouveau NavigationOnClickListener (à l'aide de setNavigationOnClickListener), vous pouvez réactiver NavDrawer ultérieurement, le cas échéant, en appelant à nouveau setDrawerListener avec votre ActionBarDrawerToggle.
straya

24
    mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
    mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // event when click home button
        }
    });

dans mon cas, ce code fonctionne parfaitement


Vous êtes vraiment génial, cela a fonctionné, je n'ai jamais pensé que je pourrais gérer le bouton de retour de la barre d'outils via DrawerToggle ..
Sai

Pour que ActionBarDrawerToggle.setToolbarNavigationClickListener fonctionne, il faut d'abord appeler ceci: mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (false); et gérez lui-même les événements de clic. (ouvrir / fermer le tiroir au clic)
luky

10

C'est ainsi que je le fais pour revenir au bon fragment, sinon si vous avez plusieurs fragments au même niveau, il reviendrait au premier si vous ne remplacez pas le comportement du bouton de retour de la barre d'outils.

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });

Avons-nous la méthode de clic "Remplacer" dans Kotlin?
Akhila Madari

@AkhilaMadari essayez quelque chose comme ça dans Kotlin: val toolbar = findViewById (R.id.toolbar) as Toolbar setSupportActionBar (toolbar) toolbar.setNavigationOnClickListener {/ * faites ce que vous voulez * / finish ()}
Marcos

3

Je pense que la bonne solution avec la bibliothèque de support 21 est la suivante

// action_bar is def resource of appcompat; 
// if you have not provided your own toolbar I mean  
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
    // change home icon if you wish
    toolbar.setLogo(this.getResValues().homeIconDrawable());
    toolbar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //catch here title and home icon click                          
        }                       
    });                 
}

dans this.getResValues().homeIconDrawable(), qui est this?
LuisComS

Ceci est une activité. Getresvalues ​​est ma méthode, donc ce n'est pas pertinent ici. Setlogo accepte un identifiant de ressource pouvant être dessiné.
Čikić Nenad

4
cela gérera le clic de l'utilisateur n'importe où dans la barre d'outils entière, je ne pense pas que ce soit ce qu'il demandait
Mina Fawzy

1

J'ai géré le bouton Retour et Accueil dans le tiroir de navigation comme

public class HomeActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {
    private ActionBarDrawerToggle drawerToggle;
    private DrawerLayout drawerLayout;
    NavigationView navigationView;
    private Context context;

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

        setContentView(R.layout.activity_home);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        resetActionBar();

        navigationView = (NavigationView) findViewById(R.id.navigation_view);
        navigationView.setNavigationItemSelectedListener(this);

        //showing first fragment on Start
        getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //listener for home
        if(id==android.R.id.home)
        {  
            if (getSupportFragmentManager().getBackStackEntryCount() > 0)
                onBackPressed();
            else
                drawerLayout.openDrawer(navigationView);
            return  true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
       if (drawerLayout.isDrawerOpen(GravityCompat.START)) 
            drawerLayout.closeDrawer(GravityCompat.START);
       else 
            super.onBackPressed();
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Begin the transaction

        Fragment fragment = null;
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (id == R.id.nav_companies_list) {
            fragment = new FirstFragment();
            // Handle the action
        } 


        // Begin the transaction
        if(fragment!=null){

            if(item.isChecked()){
                if(getSupportFragmentManager().getBackStackEntryCount()==0){
                    drawer.closeDrawers();
            }else{
                    removeAllFragments();
                    getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
                    drawer.closeDrawer(GravityCompat.START);
                }

            }else{
                removeAllFragments();
                getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
                drawer.closeDrawer(GravityCompat.START);
            }
        }

        return true;
    }

    public void removeAllFragments(){
        getSupportFragmentManager().popBackStackImmediate(null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

    public void replaceFragment(final Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                .replace(R.id.WikiCompany, fragment).addToBackStack("")
                .commit();
    }


    public void updateDrawerIcon() {
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
                    if (getSupportFragmentManager().getBackStackEntryCount() > 0)
                        drawerToggle.setDrawerIndicatorEnabled(false);
                    else
                        drawerToggle.setDrawerIndicatorEnabled(true);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }, 50);
    }

    public void resetActionBar()
    {
        //display home
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
    }

    public void setActionBarTitle(String title) {
        getSupportActionBar().setTitle(title);
    }
}

et dans chaque onViewCreatedj'appelle

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((HomeActivity)getActivity()).updateDrawerIcon();
    ((HomeActivity) getActivity()).setActionBarTitle("List");
}

0

C'est ainsi que j'ai mis en œuvre sa conception pré-matérielle et cela semble toujours fonctionner maintenant que je suis passé au nouveau Toolbar. Dans mon cas, je veux connecter l'utilisateur s'il tente d'ouvrir la navigation latérale en étant déconnecté (et attraper l'événement pour que la navigation latérale ne s'ouvre pas). Dans votre cas, vous ne pourriez pas return true;.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (!isLoggedIn() && item.getItemId() == android.R.id.home) {
        login();
        return true;
    }
    return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}

Ah, j'ai oublié que j'ai découvert que je ne pouvais pas capturer le clic du bouton d'accueil dans un fragment, j'ai posé une question ici et suggéré une solution de contournement qui consistait à transmettre manuellement l'événement à tous vos fragments. stackoverflow.com/q/21938419/1007151
darnmason

0

J'ai changé un peu le DrawerLayout pour obtenir les événements et pouvoir consommer et événement, par exemple si vous souhaitez utiliser l'actionToggle comme retour si vous êtes en vue détaillée:

public class ListenableDrawerLayout extends DrawerLayout {

    private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
    private boolean mManualCall;

    public ListenableDrawerLayout(Context context) {
        super(context);
    }

    public ListenableDrawerLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Sets the listener for the toggle button
     *
     * @param mOnToggleButtonClickedListener
     */
    public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
        this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
    }

    /**
     * Opens the navigation drawer manually from code<br>
     * <b>NOTE: </b>Use this function instead of the normal openDrawer method
     *
     * @param drawerView
     */
    public void openDrawerManual(View drawerView) {
        mManualCall = true;
        openDrawer(drawerView);
    }

    /**
     * Closes the navigation drawer manually from code<br>
     * <b>NOTE: </b>Use this function instead of the normal closeDrawer method
     *
     * @param drawerView
     */
    public void closeDrawerManual(View drawerView) {
        mManualCall = true;
        closeDrawer(drawerView);
    }


    @Override
    public void openDrawer(View drawerView) {

        // Check for listener and for not manual open
        if (!mManualCall && mOnToggleButtonClickedListener != null) {

            // Notify the listener and behave on its reaction
            if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
                return;
            }

        }
        // Manual call done
        mManualCall = false;

        // Let the drawer layout to its stuff
        super.openDrawer(drawerView);
    }

    @Override
    public void closeDrawer(View drawerView) {

        // Check for listener and for not manual close
        if (!mManualCall && mOnToggleButtonClickedListener != null) {

            // Notify the listener and behave on its reaction
            if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
                return;
            }

        }
        // Manual call done
        mManualCall = false;

        // Let the drawer layout to its stuff
        super.closeDrawer(drawerView);
    }

    /**
     * Interface for toggle button callbacks
     */
    public static interface OnToggleButtonClickedListener {

        /**
         * The ActionBarDrawerToggle has been pressed in order to open the drawer
         *
         * @return true if we want to consume the event, false if we want the normal behaviour
         */
        public boolean toggleOpenDrawer();

        /**
         * The ActionBarDrawerToggle has been pressed in order to close the drawer
         *
         * @return true if we want to consume the event, false if we want the normal behaviour
         */
        public boolean toggleCloseDrawer();
    }

}

0

L'approche la plus simple que nous pourrions faire est de changer l'icône d'accueil en icône connue et de comparer les dessinables (car l'icône android.R.id.home peut différer selon les versions d'API.

définissez donc une barre d'outils comme barre d'action SetSupportActionBar (_toolbar);

_toolbar.NavigationIcon = your_known_drawable_here;

   for (int i = 0; i < _toolbar.ChildCount; i++)
            {
                View v = _toolbar.GetChildAt(i);
                if (v is ImageButton)
                {
                    ImageButton imageButton = v as ImageButton;

                    if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
                    {
                       //here v is the widget that contains the home  icon you can add your click events here 
                    }
                }
            }

0

Dans mon cas, j'ai dû mettre l'icône en utilisant:

toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

Et puis écoutez les événements de clic avec onOptionsItemSelected par défaut et id android.R.id.home


1
Cela ne fonctionnera pas. android.R.id.homenever fire
Trancer

0

Pour tous ceux qui recherchent une implémentation Xamarin (puisque les événements sont effectués différemment en C #), j'ai simplement créé cette NavClickHandlerclasse comme suit:

public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
    private Activity mActivity;
    public NavClickHandler(Activity activity)
    {
        this.mActivity = activity;
    }
    public void OnClick(View v)
    {
        DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
        if (drawer.IsDrawerOpen(GravityCompat.Start))
        {
            drawer.CloseDrawer(GravityCompat.Start);
        }
        else
        {
            drawer.OpenDrawer(GravityCompat.Start);
        }
    }
}

Ensuite, attribuez un bouton de menu hamburger personnalisé comme celui-ci:

        SupportActionBar.SetDisplayHomeAsUpEnabled(true);
        SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
        this.drawerToggle.DrawerIndicatorEnabled = false;
        this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);

Et enfin, attribuer au menu du tiroir un basculeur ToolbarNavigationClickListener du type de classe que j'ai créé précédemment:

        this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);

Et puis vous avez un bouton de menu personnalisé, avec les événements de clic gérés.


0

Essayez ce code

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if(id == android.R.id.home){
        //You can get 
    }
    return super.onOptionsItemSelected(item);
}

Ajoutez le code ci-dessous à votre metod onCreate ()

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.