web-dev-qa-db-fra.com

Gérer la navigation de la barre d'outils et le bouton de retour de fragment dans Android

Tous mes fragments sont contrôlés par ActionBarActivity (mainActivity). Dans mainActivity, une DrawerLayout est implémentée et tous les fragments enfants sont poussés par le clic sur l'élément de liste de tiroirLayout. Le problème auquel je suis confronté est après avoir poussé un fragment à travers tiroirLayout. Je souhaite changer l'icône du tiroir en icône arrière de ToolBar afin que l'utilisateur puisse accéder au fragment précédent et gérer le rappel de Android.R.id.home dans le même fragment ou dans l'activité principale .

Le code que j'utilise est:

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

À partir du code ci-dessus, je ne parviens pas à obtenir le rappel de Android.R.id.home et le réglage du bouton principal ne fonctionne pas à chaque fois actionBar.setDisplayHomeAsUpEnabled(true);actionBar.setHomeButtonEnabled(true);

Toute aide sera vraiment appréciée.

Merci

28
Abhishek Dhiman

Vous devez gérer l'action que vous appuyez sur le bouton retour de votre activité principale car celle-ci est le conteneur de votre fragment. 

Tout d’abord, ajoutez votre tout fragment à transaction.addToBackStack (null) et maintenant l’appel du bouton de navigation retour sera activé. J'espère que le code suivant vous aidera ...

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

vous pouvez aussi utiliser 

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

Et pour changer le titre en fonction du nom de fragment de fragment, vous pouvez utiliser le code suivant:

activity.getSupportActionBar().setTitle("Keyword Report Detail");
30
Amandeep Rohila

Ajouter une barre d'outils à votre 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>

Ensuite, dans votre méthode onCreateView dans le fragment:

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

J'ai pas mal de solutions et aucune ne fonctionne parfaitement. J'ai utilisé diverses variantes de solutions disponibles dans mon projet, présentées ci-dessous. Veuillez utiliser ce code dans la classe où vous initialisez la disposition de la barre d’outils et des tiroirs.

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

Vous pouvez utiliser Toolbar à l'intérieur du fragment et il est facile à manipuler. D'abord, ajoutez la barre d'outils à la mise en page du fragment

<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>

Dans la méthode onCreateView du fragment, vous pouvez gérer la barre d’outils comme ceci.

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

Il définira la barre d'outils, le titre et la navigation de la flèche vers l'arrière sur la barre d'outils. Vous pouvez définir n'importe quelle icône sur la méthode setNavigationIcon.

Si vous devez déclencher un événement lorsque vous cliquez sur l'icône de navigation de la barre d'outils, vous pouvez l'utiliser.

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

Si votre activité comporte un tiroir de navigation, vous devrez peut-être l'ouvrir en cliquant sur le bouton de navigation arrière. vous pouvez ouvrir ce tiroir comme ça.

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

Le code complet est ici

 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;
}
7
Ishan Fernando

Probablement la solution la plus propre:

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

Utilisez simplement cette classe comme parent pour tous les fragments devant prendre en charge la navigation.

4
Appyx

OnToolBar il y a une icône de navigation à gauche

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

En utilisant cette icône de navigation à gauche, cliquez sur l'icône de navigation pour appeler l'activité parent. 

et dans manifest, nous pouvons informer le système de l'activité des parents.

  <activity
            Android:name=".CategoryCloudSelectActivity"
            Android:parentActivityName=".EventSelectionActivity"
            Android:screenOrientation="portrait" />
0
Deepak Gupta