13

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.

Boardy
  • 35,417
  • 104
  • 256
  • 447
  • What android version do you plan to support? Do you use the `ActionBarSherlock` library? – user Sep 25 '12 at 14:03
  • Technically it supports Android 2.3 and above, I know action bars only work for honeycomb upwards which is fine, as I am developing the code so if using 2.3 or below it handles the app one way and if using honeycomb or above then it can use the action bar, so no I am not using ActionBarSherlock – Boardy Sep 25 '12 at 20:39

1 Answers1

18

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

Vince
  • 1,570
  • 3
  • 27
  • 48
user
  • 86,916
  • 18
  • 197
  • 190
  • But if it is the fragment that implements the regular actionbar you'll get 2 actionbars shown at once :) – Warpzit Mar 18 '15 at 13:37
  • @Warpzit I'm not sure I understand your comment, the two action bars appearing at once(an exact scenario would be helpful to understand). – user Mar 19 '15 at 14:34
  • I had another issue >_<, the contextual actionbar didn't overlay properly, see here: http://stackoverflow.com/q/26443403/969325 – Warpzit Mar 19 '15 at 16:47