Barra degli strumenti – Passa da un cassetto all’altro pulsante con una sola attività

Ho cercato per un po ‘su come passare dall’icona di apertura / chiusura del cassetto (passando da un hamburger alla freccia) a una semplice freccia indietro. La mia applicazione al momento ha solo un’attività che cambia tra diversi frammenti. A un certo punto, voglio passare da uno dei frammenti principali (cioè uno dei frammenti nel cassetto) a un frammento che gerarchicamente si trova sotto il frammento precedente (cioè un frammento “Aggiungi nuovo”). In questo nuovo frammento, voglio che la barra degli strumenti mostri il pulsante Indietro invece del pulsante del cassetto.

Mi sono guardato intorno e ho provato diverse soluzioni per un po ‘di tempo. Ecco i più notevoli:

  • Cambia icona del cassetto retro freccia indietro – Ho rimosso con successo l’icona del cassetto, ma sul posto non c’è niente. Nessun segno di spunta, nessun pulsante indietro, nessuna icona. Sospetto che ciò sia dovuto al fatto che la mia attività non ha un genitore, ma a parte un lavoro a buon mercato (crea un’altra attività che funge da genitore che avvia l’attività principale), sono persa nel fare ciò che devo fare.
  • Passaggio tra l’immagine di Android Navigation Drawer e Up caret quando si usano i frammenti – Simile a quanto sopra, ha ancora molti più dettagli. In definitiva, l’icona continua a non trasformarsi in un pulsante indietro.
  • La barra degli strumenti di Android lollipop cambia tra il pulsante di apertura / chiusura e il pulsante posteriore : lo trovo difficile da seguire, ma alla fine l’icona del cassetto può essere sfruttata e non fa nulla (anche se credo di sapere come farlo agire come una stampa posteriore). Tuttavia, l’icona non cambia.

Al momento, sto pensando a un metodo lungo e arduo per creare un’icona personalizzata che nascondo e mostri (e nasconda / mostri l’icona del cassetto nativo). Tuttavia, c’è un modo migliore per passare da un cassetto all’altro?

Come una domanda a parte relativa, ho esaminato i documenti di Material Design e alcuni esempi hanno una X nell’angolo in alto a sinistra. Quanto è diverso da implementare rispetto all’attuazione dei pulsanti cassetto vs back / su?

grazie ~

Modificare:

Posso capire come sostituire l’icona, ma come otterrei l’evento click?

Finora, questo è stato il mio miglior vantaggio:

  • Imansible catturare l’evento click del pulsante home della barra degli strumenti

Quello che ho provato ora:

  • Disabilitato il DrawerToggle quando necessario (cioè, mDrawerToggle.setDrawerIndicatorEnabled(useDrawer); )
  • Aggiunti i log in onOptionsItemSelected nel mio NavigationDrawerFragment, nella mia attività, nonché nel DialogFragment che sto testando attualmente, che viene eseguito se item.getItemId() == android.R.id.home è true. Nessuna di queste dichiarazioni di registro si spegne

Per un contesto migliore, ora ho un frammento a schermo intero che aggiunge un pulsante “Salva” al menu e cambia l’icona del cassetto in una “X”. Il frammento può ottenere l’evento del menu di salvataggio, ma nemmeno l’Activity e il Drawer possono ottenere quando viene toccata la X.

Edit2:

Come richiesto, ecco un codice. Si noti che questo è tutto da questo repository di Github , sul quale sto lavorando triggersmente (si noti che ho alcune funzioni inutili qua o là dal test rapido).

ActivityMain :

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Add the toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); if (mToolbar != null) { setSupportActionBar(mToolbar); } // Initialize the drawer mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); // Set up the drawer mNavigationDrawerFragment.setUp( R.id.navigation_drawer, (DrawerLayout) findViewById(R.id.drawer_layout), mToolbar); // TODO: Check if this helps to catch the main toolbar button click getSupportActionBar().setDisplayShowHomeEnabled(true); // Get the titles for the Toolbar mTitles = getResources().getStringArray(R.array.drawer_items); mDrawerPosition = -1; if (savedInstanceState == null) { // If there was no saved position, then the default, starting position should be used forceChangeItemSelected(0); } else { // Otherwise, get the saved position from the bundle int position = savedInstanceState.getInt(KEY_DRAWERPOS); mNavigationDrawerFragment.setSelectedItem(position); // Title needs to be re-set getSupportActionBar().setTitle(mTitles[position]); } // If I include the below bit, then the DrawerToggle doesn't function // I don't know how to switch it back and forth mToolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d(LOG_TAG, "Navigation was clicked"); } }); } @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. Log.d(LOG_TAG, "Activity responding to menu click..."); if(item.getItemId() == android.R.id.home) Log.d(LOG_TAG, "Activity got it...."); // If the fragment is supposed to handle things, then let it if(mIsFragmentHandlingMenus) return false; int id = item.getItemId(); if(id == R.id.save) { // This isn't implemented! If chosen, then there's a bug! Log.e(LOG_TAG, "onOptionsItemSelected: Save was selected!"); } return super.onOptionsItemSelected(item); } @Override public void fragmentHandlingMenus(boolean isFragmentHandlingMenus) { // Simply store the setting mIsFragmentHandlingMenus = isFragmentHandlingMenus; // Toggle the drawer as necessary mNavigationDrawerFragment.toggleDrawerUse(!isFragmentHandlingMenus); } 

NavigationDrawerFragment :

 public void toggleDrawerUse(boolean useDrawer) { // Enable/Disable the icon being used by the drawer mDrawerToggle.setDrawerIndicatorEnabled(useDrawer); // TODO: Enable/Disable the drawer even being able to open/close } @Override public boolean onOptionsItemSelected(MenuItem item) { Log.d(LOGTAG, "Drawer responding to menu click..."); if(item.getItemId() == android.R.id.home) Log.d(LOGTAG, "Drawer got it...."); if (mDrawerToggle.onOptionsItemSelected(item)) { return true; } return super.onOptionsItemSelected(item); } 

GoalAdderFragment :

 @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Allow this fragment to handle toolbar menu items setHasOptionsMenu(true); // Set up the toolbar ((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); ((ActionBarActivity) getActivity()).getSupportActionBar().setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel); ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(getResources().getString(R.string.title_addgoal)); } @Override public void onAttach(Activity activity) { super.onAttach(activity); // Cache the Activity as the frag handler if necessary if(mFragHandler == null) mFragHandler = (TransactionHandler.FragmentTransactionHandler) getActivity(); // Tell the Activity to let fragments handle the menu events mFragHandler.fragmentHandlingMenus(true); } @Override public void onDetach() { super.onDetach(); // Tell the Activity that it can now handle menu events once again mFragHandler.fragmentHandlingMenus(false); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.save_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { Log.d(LOGTAG, "Item id: " + item.getItemId() + " | Save id: " + R.id.save); Toast.makeText(getActivity(), "Fragment activated!", Toast.LENGTH_SHORT).show(); switch (item.getItemId()) { case R.id.save: return true; case android.R.id.home: return true; default: break; } return false; } 

Soluzione:

Questa è l’ultima soluzione alla quale sono finito, con l’aiuto della risposta accettata qui sotto:

NavigationDrawerFragment :

 private View.OnClickListener mOriginalListener; public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) { /* Rest of setting up code */ // Save the default listener after setting everything else up mOriginalListener = mDrawerToggle.getToolbarNavigationClickListener(); } // Tells the toolbar+drawer to switch to the up button or switch back to the normal drawer public void toggleDrawerUse(boolean useDrawer) { // Enable/Disable the icon being used by the drawer mDrawerToggle.setDrawerIndicatorEnabled(useDrawer); // Switch between the listeners as necessary if(useDrawer) mDrawerToggle.setToolbarNavigationClickListener(mOriginalListener); else mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getActivity(), "Custom listener", Toast.LENGTH_SHORT).show(); } }); } 

Solutions Collecting From Web of "Barra degli strumenti – Passa da un cassetto all’altro pulsante con una sola attività"

Probabilmente non è quello che vorresti sentire, ma anche da un punto di vista concettuale preferirei una nuova attività piuttosto che un frammento.

La tua attività principale è strettamente legata al cassetto, quindi caricare un nuovo frammento senza alcun accesso al cassetto non ha senso per me (ma sentiti libero di aspettare altre risposte se la pensi così). Una nuova attività risolverebbe entrambi i problemi, poiché non avrebbe alcun cassetto e potrebbe essere figlio di quello principale.

Anche la tua domanda a parte sembra azzeccata. Un’attività “Aggiungi nuovo” potrebbe adattarsi perfettamente al modello visivo della “finestra di dialogo a schermo intero” dalle linee guida. Vedere:

http://www.google.com/design/spec/components/dialogs.html#dialogs-full-screen-dialogs

Questo modello ha un “salva”, un pulsante positivo in alto a destra e una X. Concettualmente, il pulsante X serve per annullare / interrompere un processo, piuttosto che navigare su alcuni backstack. Significa che stai licenziando qualcosa senza che si verifichi alcuna azione. Questo si adatta bene per quello che vuoi fare.

Dal punto di vista del design, è facilmente creato da una nuova Activity , che può rimanere al di sopra degli altri. Inoltre, se il punto dei frammenti è fondamentalmente in grado di rappresentare due o più contemporaneamente in compresse e schermo più grande – di nuovo – non sarei così felice con un vecchio frammento alla mia sinistra e un frammento “Aggiungi nuovo” sulla destra .

Piuttosto – su tablet – vorrei fare una finestra di dialogo mobile, come suggerito dalle linee guida.

http://www.google.com/design/spec/components/dialogs.html#dialogs-confirmation-dialogs

Attività a schermo intero con un pulsante X per i telefoni e finestra di dialogo mobile (con i pulsanti in basso) per i tablet. Questo, per me, è l’approccio più coerente con le linee guida.


Raccomando di leggere l’intero link. Sulla differenza tra < - e X,

La X differisce da una freccia su, che viene utilizzata quando lo stato della vista viene costantemente salvato o quando le app dispongono di funzionalità di bozza o salvataggio automatico. Ad esempio, una freccia su viene utilizzata in Impostazioni perché tutte le modifiche vengono immediatamente eseguite.

E anche

Toccando la X in questo esempio di Impostazioni , tutte le modifiche verranno ignorate. Le modifiche verranno salvate solo toccando Salva.

Inserisci questo codice in onCreate() della tua Activity . Funziona bene per me. Anche usando compileSdk 23 e versioni successive.

  drawer = (DrawerLayout) findViewById(R.id.drawer_layout); final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); if(toolbar != null) { toggle = new ActionBarDrawerToggle( this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); toggle.syncState(); drawer.setDrawerListener(toggle); getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { getSupportActionBar().setDisplayHomeAsUpEnabled(true); // show back button toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onBackPressed(); } }); } else { //show hamburger getSupportActionBar().setDisplayHomeAsUpEnabled(false); toggle.syncState(); toolbar.setNavigationOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { drawer.openDrawer(GravityCompat.START); } }); } } }); 

Dovrebbe funzionare anche per l’ultima API 24 .

Nella tua attività onCreate() fai questo:

 final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); final DrawerLayout drawer = (DrawerLayout) view.findViewById(R.id.drawer_layout); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); final View.OnClickListener originalToolbarListener = toggle.getToolbarNavigationClickListener(); getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { @Override public void onBackStackChanged() { if (getSupportFragmentManager().getBackStackEntryCount() > 0) { toggle.setDrawerIndicatorEnabled(false); toggle.setToolbarNavigationClickListener(new View.OnClickListener() { @Override public void onClick(View v) { getSupportFragmentManager().popBackStack(); } }); } else { toggle.setDrawerIndicatorEnabled(true); toggle.setToolbarNavigationClickListener(originalToolbarListener); } } }); 

La risposta di @matusalem funziona alla grande. Ho solo aggiunto un po ‘- fai attenzione perché il cassetto può essere aperto scorrendo dal lato sinistro dello schermo. Per alcuni, questo può essere desiderato, ma per me stavo disabilitando il cassetto perché non aveva senso in nessun frammento ma il mio frammento principale. Il colpo è facilmente disabilitato qui – Cassetto di navigazione – disabilita lo scorrimento

Questo probabilmente appartiene ad un commento alla risposta, ma non ho abbastanza reputazione. Mie scuse.

Ho avuto lo stesso problema con il passaggio tra menu hamburger e freccia indietro all’interno della stessa attività quando si cambiavano i frammenti. Ecco la mia soluzione di lavoro, spero che aiuti qualcuno.

Ascoltatore all’interno della tua attività:

 private View.OnClickListener toolbarMenuListener = new View.OnClickListener() { @Override public void onClick(View v) { //will be called only if toggle.setDrawerIndicatorEnabled(false); ! Log.v(tag,"toggle onClick:"+v.getId()+" android.R.id.home:"+android.R.id.home); onBackPressed(); } }; 

Code onCreate () qualcosa come:

 ... ... setSupportActionBar(toolbar); toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); drawer.addDrawerListener(toggle); toggle.syncState(); //set listener so you know when back on arrow is pressed toggle.setToolbarNavigationClickListener(toolbarMenuListener); ... ... 

Parte a cui sei interessato con commenti (la class restituita è parte della mia class, può essere annullata):

 /** * Method to set up action bar drawer. * @param enableBackDrawerIcon set true if want to show drawer back arrow, * false to show hamburger menu. * @param title shown next to drawer icon */ public BaseMenusActivity drawerSetupToggle(boolean enableBackDrawerIcon, String title) { //NOTE: order of methods call is important! // If you change order order of setDrawerIndicatorEnabled and setDisplayHomeAsUpEnabled // method calls it won't work, weird bugs will happen (like no icon at all) if(enableBackDrawerIcon){ Log.v(tag,"show drawer back icon"); //hides hamburger menu and enables View.OnClickListener to be called toggle.setDrawerIndicatorEnabled(false); //show back arrow if(getSupportActionBar()!=null) getSupportActionBar().setDisplayHomeAsUpEnabled(true); } else { Log.v(tag,"show hamburger menu"); //hide back arrow if(getSupportActionBar()!=null) getSupportActionBar().setDisplayHomeAsUpEnabled(false); //shows hamburger menu and prevents View.OnClickListener to be called toggle.setDrawerIndicatorEnabled(true); } setTitle(title); return this; } 

NOTA : l’ordine dei metodi chiamati è importante! Sarebbe meglio se potessi semplicemente scriverlo in 2 righe come questa ma NON FUNZIONERÀ (almeno per me):

 toggle.setDrawerIndicatorEnabled(!enableBackDrawerIcon); getSupportActionBar().setDisplayHomeAsUpEnabled(enableBackDrawerIcon); 

Se sei interessato al motivo per cui l’ordine del metodo richiama le cose, cerca l’implementazione di questi metodi.