No se puede capturar el evento de clic del botón de inicio de la barra de herramientas

106

Implementé la biblioteca appcompat más nueva y utilicé la Toolbarbarra de acciones como. Pero el problema es que no puedo captar el evento de clic del botón de inicio / icono de hamburguesa. He intentado y buscado todo, pero no parece encontrar un problema similar.

Esta es mi Activityclase:

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);
}

Y esta es mi clase 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);
}

cuando hago clic en un elemento del menú, se llama al registro "elemento seleccionado". Pero cuando hago clic en el botón de inicio, se abre el cajón de navegación, pero nunca se llama al registro de "inicio seleccionado". También configuré un onOptionsItemSelectedmétodo dentro de mi Activity, pero todavía no se llama.

Leonhart oscuro
fuente

Respuestas:

224

Si desea saber cuándo se hace clic en Inicio, AppCompatActivityentonces debería intentarlo así:

Primero dile a Android que quieres usar tu Toolbarcomo tu ActionBar:

setSupportActionBar(toolbar);

Luego configure Inicio para que se muestre de setDisplayShowHomeEnabledesta manera:

getSupportActionBar().setDisplayShowHomeEnabled(true);

Finalmente, escuche los eventos de clic android.R.id.homecomo de costumbre:

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

Si desea saber cuándo se hace clic en el botón de navegación Toolbaren una clase que AppCompatActivityno sea , puede usar estos métodos para configurar un icono de navegación y escuchar eventos de clic en él. El icono de navegación aparecerá en el lado izquierdo de su Toolbardonde solía estar el botón "Inicio".

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 desea saber cuando se hace clic en la hamburguesa y cuando el cajón se abre, ya está escuchando para estos eventos a través onDrawerOpenedy onDrawerClosedpor lo que usted desee para ver si estas devoluciones de llamada se ajustan a sus necesidades.

MrEngineer13
fuente
1
Probé la primera parte antes, pero no funciona. Probé la segunda parte y funciona. Pero el icono no cambia si registro la barra de herramientas con el cajón de navegación. Una pregunta más, ¿hay algún reemplazo para setDrawerIndicatorEnabled para esto? Lo intenté con este nuevo cajón de navegación y obtuve un error. Thank u
Dark Leonhart
La segunda solución está funcionando. Pero, ¿cómo podemos detectar el botón de inicio y el botón del cajón en la segunda solución? Cuando hago clic en el icono del cajón, no abre el cajón.
Dory
2
Cuando estableceNavigationOnClickListener para la barra de herramientas, pierde el comportamiento de cajón "nativo" :(
IlyaEremin
7
Entonces, ahora necesitamos un oyente de clics separado cuando antes en los fragmentos podíamos verificar android.R.id.home en onOptionsItemSelected ()? Eso es realmente muy molesto
Daniel Wilson
1
re: Toolbar, si configura un nuevo NavigationOnClickListener (usando setNavigationOnClickListener) puede restablecer el NavDrawer más tarde cuando sea apropiado llamando a setDrawerListener nuevamente con su ActionBarDrawerToggle.
straya
24
    mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
    mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // event when click home button
        }
    });

en mi caso este código funciona perfecto

vuhung3990
fuente
Eres realmente genial, funcionó, nunca pensé que podría manejar el botón de retroceso de la barra de herramientas a través de DrawerToggle ..
Sai
Para que ActionBarDrawerToggle.setToolbarNavigationClickListener funcione, primero debe llamar a esto: mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (falso); y gestionar los eventos de clic él mismo. (abrir / cerrar cajón al hacer clic)
luky
10

Así es como lo hago para volver al fragmento correcto; de lo contrario, si tiene varios fragmentos en el mismo nivel, volvería al primero si no anula el comportamiento del botón de retroceso de la barra de herramientas.

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });
Marcos
fuente
¿Tenemos el método de clic "Anular" en Kotlin?
Akhila Madari
@AkhilaMadari prueba algo como esto en Kotlin: val toolbar = findViewById (R.id.toolbar) as Toolbar setSupportActionBar (barra de herramientas) toolbar.setNavigationOnClickListener {/ * haz algo que quieras * / finish ()}
Marcos
3

Creo que la solución correcta con la biblioteca de soporte 21 es la siguiente

// 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                          
        }                       
    });                 
}
Čikić Nenad
fuente
en this.getResValues().homeIconDrawable(), ¿Quién es this?
LuisComS
Esta es una actividad. Getresvalues ​​es mi método, por lo que no es relevante aquí. Setlogo acepta una identificación de recurso dibujable.
Čikić Nenad
4
esto manejará el clic del usuario en cualquier lugar en toda la barra de herramientas, no creo que esto sea lo que estaba preguntando
Mina Fawzy
1

He manejado el botón Atrás y Inicio en el panel de navegación como

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);
    }
}

y en cada uno onViewCreatedllamo

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

Así es como lo implementé en el diseño de materiales previos y parece que todavía funciona ahora que me cambié al nuevo Toolbar. En mi caso, quiero que el usuario inicie sesión si intenta abrir el navegador lateral mientras está desconectado (y captar el evento para que el navegador lateral no se abra). En tu caso no podrías 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);
}
darnmason
fuente
Ah, olvidé que descubrí que no pude captar el clic del botón de inicio en un fragmento, hice una pregunta aquí y sugerí una solución alternativa que era pasar manualmente el evento a todos sus fragmentos. stackoverflow.com/q/21938419/1007151
darnmason
0

Cambié un poco DrawerLayout para obtener los eventos y poder consumir un evento, por ejemplo, si desea usar actionToggle como atrás si está en la vista detallada:

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();
    }

}
Adrian
fuente
0

El enfoque más fácil que podríamos hacer es cambiar el ícono de inicio a un ícono conocido y comparar elementos de diseño (porque el ícono de android.R.id.home puede diferir de las diferentes versiones de la API

así que configure una barra de herramientas como barra de acción 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 
                    }
                }
            }
Sajidh Zahir
fuente
0

En mi caso tuve que poner el icono usando:

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

Y luego escuche los eventos de clic con onOptionsItemSelected predeterminado y android.R.id.home id

Diego Laballos
fuente
1
Esto no funcionará. android.R.id.home
Never
0

Para cualquiera que busque una implementación de Xamarin (dado que los eventos se realizan de manera diferente en C #), simplemente creé esta NavClickHandlerclase de la siguiente manera:

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);
        }
    }
}

Luego, asigne un botón de menú de hamburguesa personalizado como este:

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

Y finalmente, asigné al alternador del menú del cajón un ToolbarNavigationClickListener del tipo de clase que creé anteriormente:

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

Y luego tienes un botón de menú personalizado, con eventos de clic manejados.

Trevor Hart
fuente
0

Prueba este código

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

Agregue el siguiente código a su método onCreate ()

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
Faxriddin Abdullayev
fuente