Search code examples
androidandroid-listfragment

Using Contextual action bar with fragments


I am currently working on android project and making use of fragments and ListViews/ListFragments. I have contextual action bars working on standard activities such as a ListActivity.

Now I am trying to do the same sort of thing but on a fragment layout. I have a MainActivity which extends Activity which inflates the XML for the layout that contains the 2 fragments, fragment A and fragment B.

Fragment A extends ListFragment and contains a ListView which is populated from data within an SQLite Database. When I have got a contextual action bar working on a standard ListActivity I have a class that Extends ListView.MultiChoiceModeListener but this isn't available for a ListFragment class or a standard activity so how would I go about implementing this.

The basic thing I want to achieve is when someone long presses the item within a ListView within FragmentA which extends ListFragment, the action bar contextually changes and the user can then select multiple items from within the ListView.

Thanks for any help you can provide.


Solution

  • When I have got a contextual action bar working on a standard ListActivity I have a class that Extends ListView.MultiChoiceModeListener but this isn't available for a ListFragment class or a standard activity so how would I go about implementing this.

    I don't see how MultiChoiceModeListener isn't available (maybe I didn't understand what you try to do). From your comment I assumed you use the fragments from the compatibility package. Below is an example with a FragmentActivity with two static fragments and each of those fragments triggers the contextual action bar with their own menus options.

    The FragmentActivity is very simple, it just holds the two fragments below:

    // the list fragment
    public class ListCABFragment extends ListFragment {
    
        private String[] mCountries = { "Romania", "Germany", "England", "USA",
                "Japan", "France" };
        private static final boolean POST_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            if (POST_HONEYCOMB) {
                // make sure we are on a version above Honeycomb otherwise will
                // access things that aren't available
                postHoneycombCAB();
            } else {
                // probably do nothing and implement the normal context menu?!?
            }
            setListAdapter(new ArrayAdapter<String>(getActivity(),
                    android.R.layout.simple_list_item_1, mCountries));
        }
    
        @SuppressLint({ "NewApi", "NewApi" })
        private void postHoneycombCAB() {
            getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
            getListView().setOnItemLongClickListener(new OnItemLongClickListener() {
    
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view,
                        int position, long id) {
                    ((ListView) parent).setItemChecked(position,
                            ((ListView) parent).isItemChecked(position));
                    return false;
                }
            });
            getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() {
    
                private int nr = 0;
    
                @Override
                public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                    getActivity().getMenuInflater().inflate(R.menu.listcab_menu,
                            menu);
                    return true;
                }
    
                @Override
                public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                    return false;
                }
    
                @Override
                public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                    switch (item.getItemId()) {
                    case R.id.item1:
                        Toast.makeText(getActivity(), "Option1 clicked",
                                Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.item2:
                        Toast.makeText(getActivity(), "Option2 clicked",
                                Toast.LENGTH_SHORT).show();
                        break;
    
                    }
                    return false;
                }
    
                @Override
                public void onDestroyActionMode(ActionMode mode) {
                    nr = 0;
                }
    
                @Override
                public void onItemCheckedStateChanged(ActionMode mode,
                        int position, long id, boolean checked) {
                    if (checked) {
                        nr++;
                    } else {
                        nr--;
                    }
                    mode.setTitle(nr + " rows selected!");
                }
            });
        }
    }
    

    and the other fragment for a Fragment which has a layout composed from a RadioGroup which triggers the CAB when a RadioButton is selected:

    public class SimpleCABFragment extends Fragment implements Callback {
    
        private static final boolean POST_HONEYCOMB = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            return inflater.inflate(R.layout.frag_simplecabfragment, container,
                    false);
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            RadioGroup rg = (RadioGroup) getView().findViewById(R.id.radioGroup1);
            rg.setOnCheckedChangeListener(new OnCheckedChangeListener() {
    
                @Override
                public void onCheckedChanged(RadioGroup group, int checkedId) {
                    if (POST_HONEYCOMB) {
                        // this could be improved so we don't need to create the
                        // option
                        // menu if it is already available
                        getActivity().startActionMode(SimpleCABFragment.this);
                    } else {
                        // something else
                    }
                }
            });
        }
    
        @Override
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            if (item.getItemId() == R.id.itemradio) {
                Toast.makeText(getActivity(), "CAB for Radiogroup!",
                        Toast.LENGTH_SHORT).show();
            }
            return false;
        }
    
        @Override
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            getActivity().getMenuInflater().inflate(R.menu.simplecab_menu, menu);
            return true;
        }
    
        @Override
        public void onDestroyActionMode(ActionMode mode) {
        }
    
        @Override
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            return false;
        }
    }
    

    See if this is what you're looking for (you can find a full sample including the layouts and menus files in my github project).