19

Tutti i miei frammenti sono controllati tramite ActionBarActivity (mainActivity), all'interno di mainActivity è implementato uno DrawerLayout e tutti i frammenti figlio vengono spostati attraverso il click dell'elenco di drawerLayout. Il problema che sto affrontando è dopo aver spinto un frammento attraverso drawerLayout Voglio cambiare l'icona del cassetto nell'icona posteriore di ToolBar in modo che l'utente possa navigare al frammento precedente e gestire la callback di android.R.id.home all'interno dello stesso frammento o all'interno di mainActivity .Gestisci la barra degli strumenti di navigazione e il pulsante Indietro da frammento in Android

Il codice che sto usando è:

MainActivity.java

public class MainActivity extends ActionBarActivity { 
    private DrawerLayout layoutDrawer; 
    private ActionBarDrawerToggle drawerToggler; 
    private Stack<Fragment> stack; 

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

     Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 
     setSupportActionBar(toolbar); 
     stack = new Stack<Fragment>(); 
     layoutDrawer = (DrawerLayout) findViewById(R.id.layout_drawer); 
     drawerToggler = new ActionBarDrawerToggle(this, layoutDrawer, toolbar, 
       R.string.app_name, R.string.app_name); 
     layoutDrawer.setDrawerListener(drawerToggler); 

     setUpDrawerList(); 
     pushFragment(new FirstFragment(), true); 

     Session.setContext(getApplicationContext()); 
    } 

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

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     if (drawerToggler.isDrawerIndicatorEnabled() 
       && drawerToggler.onOptionsItemSelected(item)) 
      return true; 
     switch (item.getItemId()) { 
     case android.R.id.home: 
      Toast.makeText(this, "Back from activity", Toast.LENGTH_SHORT) 
        .show(); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 

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

    @Override 
    public void onBackPressed() { 
     popFragment(); 
    } 

    private void setUpDrawerList() { 
     ListView listView = (ListView) findViewById(R.id.list_drawer); 
     ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, 
       android.R.layout.simple_list_item_1, 
       Arrays.asList(new String[] { "First Fragment", 
         "Second Fragment" })); 
     listView.setAdapter(adapter); 
     listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 

      @Override 
      public void onItemClick(AdapterView<?> parent, View view, 
        int position, long id) { 
       layoutDrawer.closeDrawers(); 
       drawerToggler.setDrawerIndicatorEnabled(false); 
       getSupportActionBar().setDisplayHomeAsUpEnabled(true); 
       pushFragment(getFragment(position), true); 
      } 
     }); 
    } 

    private Fragment getFragment(int pos) { 
     switch (pos) { 
     case 0: 
      return new FirstFragment(); 
     case 1: 
      return new SecondFragment(); 
     } 
     return null; 
    } 

    public void pushFragment(Fragment fragment, boolean add) { 
     FragmentTransaction transation = getSupportFragmentManager() 
       .beginTransaction(); 
     if (add) 
      stack.push(fragment); 
     transation.replace(R.id.layout_content, fragment); 
     transation.commit(); 
    } 

    public void popFragment() { 
     if (!stack.isEmpty()) { 
      Fragment fragment = stack.elementAt(stack.size() - 2); 
      stack.pop(); 
      pushFragment(fragment, false); 
     } else 
      super.onBackPressed(); 
     drawerToggler.setDrawerIndicatorEnabled(stack.size() == 1); 
    } 

    public void clearBackStack() { 
     stack.clear(); 
    } 
} 

FirstFragment.java

public class FirstFragment extends Fragment { 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     setHasOptionsMenu(true); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
      Bundle savedInstanceState) { 
     return inflater.inflate(R.layout.fragment_first, container, false); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     ActionBar actionBar = ((ActionBarActivity)getActivity()).getSupportActionBar(); 
     actionBar.setTitle("First Fragment"); 
     actionBar.setDisplayHomeAsUpEnabled(true); 
     actionBar.setHomeButtonEnabled(true); 
    } 

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

    @Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
     switch(item.getItemId()) { 
     case android.R.id.home: 
      Toast.makeText(getActivity(), "Back from fragment", Toast.LENGTH_SHORT).show(); 
      getActivity().onBackPressed(); 
      return true; 
     } 
     return super.onOptionsItemSelected(item); 
    } 
} 

Dal codice di cui sopra non sono in grado di ottenere la richiamata di android.R.id.home e l'impostazione del pulsante home non funzionano ogni volta actionBar.setDisplayHomeAsUpEnabled(true);actionBar.setHomeButtonEnabled(true);

Qualsiasi aiuto sarà davvero apprezzato.

Grazie

+1

https://github.com/tekinarslan/AndroidMaterialDesignToolbar in questo modo è possibile ottenere lo stesso comportamento desiderato –

risposta

22

si deve gestire il tuo pulsante indietro premuto azione sulla vostra attività principale perché la vostra attività principale è il contenitore per il frammento.

Per prima cosa, aggiungi il tuo frammento a transaction.addToBackStack (null) e ora la funzione di pulsante di navigazione indietro continuerà con l'attività principale. Spero seguente codice vi aiuterà a ...

@Override 
    public boolean onOptionsItemSelected(MenuItem item) { 
    switch (item.getItemId()) { 
    case android.R.id.home: 
     onBackPressed(); 
     } 
    return super.onOptionsItemSelected(item); 
} 

è anche possibile utilizzare

Fragment fragment =fragmentManager.findFragmentByTag(Constant.TAG); 
if(fragment!=null) {   
     FragmentTransaction transaction = fragmentManager.beginTransaction(); 
     transaction.remove(fragment).commit(); 
} 

E per cambiare il titolo in base al nome frammento di frammento è possibile utilizzare il seguente codice:

activity.getSupportActionBar().setTitle("Keyword Report Detail"); 
+1

Attenzione che è necessario richiamare 'return true' dopo' onBackPressed() 'perché funzioni. Se non si 'onBackPressed()' non avrà alcun effetto poiché la chiamata verrà consumata da 'super.onOptionsItemSelected (item)' – hanspeide

0

OnToolBar c'è un icona di navigazione sul lato sinistro

Toolbar toolbar = (Toolbar) findViewById(R.id.tool_bar); 
     toolbar.setTitle(getResources().getString(R.string.title_activity_select_event)); 
     setSupportActionBar(toolbar); 

     getSupportActionBar().setDisplayShowHomeEnabled(true); 
     getSupportActionBar().setDisplayHomeAsUpEnabled(true); 

Usando questa icona di navigazione sul lato sinistro compaiono e sull'icona di navigazione, fare clic su di esso chiama attività principale.

e in manifest possiamo notificare il sistema sull'attività dei genitori.

<activity 
      android:name=".CategoryCloudSelectActivity" 
      android:parentActivityName=".EventSelectionActivity" 
      android:screenOrientation="portrait" /> 
+1

Questo non funziona con i frammenti. –

3

È possibile utilizzare la barra degli strumenti all'interno del frammento ed è facile da gestire. Prima aggiungi barra degli strumenti per il layout del frammento

<android.support.v7.widget.Toolbar 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/toolbar" 
    android:layout_height="wrap_content" 
    android:layout_width="match_parent" 
    android:fitsSystemWindows="true" 
    android:minHeight="?attr/actionBarSize" 
    app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" 
    android:background="?attr/colorPrimaryDark"> 
</android.support.v7.widget.Toolbar> 

all'interno del metodo onCreateView nel frammento è possibile gestire la barra degli strumenti come questo.

Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar); 
toolbar.setTitle("Title"); 
toolbar.setNavigationIcon(R.drawable.ic_arrow_back); 

IT imposterà la barra degli strumenti, il titolo e la parte posteriore freccia di navigazione per toolbar.You può impostare qualsiasi icona per il metodo setNavigationIcon.

Se è necessario attivare qualsiasi evento quando si fa clic sull'icona di navigazione della barra degli strumenti è possibile utilizzare questo.

toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      //handle any click event 
    }); 

Se la tua attività ha un cassetto di navigazione potrebbe essere necessario aprirlo quando fai clic sul pulsante di navigazione indietro. puoi aprire quel cassetto in questo modo.

toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout); 
      drawer.openDrawer(Gravity.START); 
     } 
    }); 

codice completa è qui

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
    //inflate the layout to the fragement 
    view = inflater.inflate(R.layout.layout_user,container,false); 

    //initialize the toolbar 
    Toolbar toolbar = (Toolbar) view.findViewById(R.id.toolbar); 
    toolbar.setTitle("Title"); 
    toolbar.setNavigationIcon(R.drawable.ic_arrow_back); 
    toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      //open navigation drawer when click navigation back button 
      DrawerLayout drawer = (DrawerLayout) getActivity().findViewById(R.id.drawer_layout); 
      drawer.openDrawer(Gravity.START); 
     } 
    }); 
    return view; 
} 
14

Aggiungere una barra degli strumenti al tuo xml

<android.support.v7.widget.Toolbar 
    android:id="@+id/toolbar" 
    android:layout_width="match_parent" 
    android:layout_height="?attr/actionBarSize" 
    android:background="?attr/colorPrimary" 
    android:theme="@style/ThemeOverlay.AppCompat.ActionBar" 
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Fragment title"/> 

</android.support.v7.widget.Toolbar> 

Poi all'interno del vostro metodo di onCreateView nel frammento:

Toolbar toolbar = view.findViewById(R.id.toolbar); 
toolbar.setNavigationIcon(R.drawable.ic_back_button); 
toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     getActivity().onBackPressed(); 
    } 
}); 
+1

Grazie per la risposta che ha risolto il mio problema. –

11

ho la testa attorno a molte soluzioni e no nessuno di loro funziona perfettamente. Ho usato la variazione delle soluzioni disponibili nel mio progetto che è qui di seguito. Utilizzare questo codice all'interno della classe in cui si inizializza la barra degli strumenti e il layout del cassetto.

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { 
     @Override 
     public void onBackStackChanged() { 
      if (getSupportFragmentManager().getBackStackEntryCount() > 0) { 
       drawerFragment.mDrawerToggle.setDrawerIndicatorEnabled(false); 
       getSupportActionBar().setDisplayHomeAsUpEnabled(true);// show back button 
       toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         onBackPressed(); 
        } 
       }); 
      } else { 
       //show hamburger 
       drawerFragment.mDrawerToggle.setDrawerIndicatorEnabled(true); 
       getSupportActionBar().setDisplayHomeAsUpEnabled(false); 
       drawerFragment.mDrawerToggle.syncState(); 
       toolbar.setNavigationOnClickListener(new View.OnClickListener() { 
        @Override 
        public void onClick(View v) { 
         drawerFragment.mDrawerLayout.openDrawer(GravityCompat.START); 
        } 
       }); 
      } 
     } 
    }); 
+0

Dopo aver provato un paio di soluzioni finalmente ha funzionato per me. – Sharad

+0

Funziona bene, ho aggiunto una riga alla fine di show hamburguer else ( drawer.setDrawerLockMode (DrawerLayout.LOCK_MODE_UNLOCKED);) e un'altra alla fine del (if (getSupportFragmentManager(). GetBackStackEntryCount()> 0)) che is (drawer.setDrawerLockMode (DrawerLayout.LOCK_MODE_LOCKED_CLOSED);) in modo che l'utente non possa aprire il cassetto trascinandolo quando viene mostrata la freccia indietro – Setar

+0

Questo è così poco chiaro ... cos'è 'drawerFragment', che cos'è' mDrawerToggle'? Esempio eclatante di una cattiva risposta –

0

Probabilmente la soluzione più pulita:

abstract class NavigationChildFragment : Fragment() { 

    abstract fun onCreateChildView(inflater: LayoutInflater, 
            container: ViewGroup?, 
            savedInstanceState: Bundle?): View? 

    override fun onCreateView(inflater: LayoutInflater, 
           container: ViewGroup?, 
           savedInstanceState: Bundle?): View? { 
     val activity = activity as? MainActivity 
     activity?.supportActionBar?.setDisplayHomeAsUpEnabled(true) 
     setHasOptionsMenu(true) 
     return onCreateChildView(inflater, container, savedInstanceState) 
    } 

    override fun onDestroyView() { 
     val activity = activity as? MainActivity 
     activity?.supportActionBar?.setDisplayHomeAsUpEnabled(false) 
     setHasOptionsMenu(false) 
     super.onDestroyView() 
    } 

    override fun onOptionsItemSelected(item: MenuItem): Boolean { 
     val activity = activity as? MainActivity 
     return when (item.itemId) { 
      android.R.id.home -> { 
       activity?.onBackPressed() 
       true 
      } 
      else    -> super.onOptionsItemSelected(item) 
     } 
    } 
} 

Basta usare questa classe come genitore per tutti i frammenti che dovrebbero sostenere la navigazione.