Using Contextual action bar with fragments

Boardy picture Boardy · Sep 18, 2012 · Viewed 10.8k times · Source

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.

Answer

user picture user · Sep 26, 2012

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