Multiple selection in custom ListView with CAB

前端 未结 3 788
孤城傲影
孤城傲影 2020-11-28 21:43

After reading and try\'n\'error for days, I´m giving up and ask for help.

< edit > I am using ActionBarSherlock. < /edit >

What I want to achie

相关标签:
3条回答
  • 2020-11-28 22:30

    See if the code helps you(it's basically a ListActivity with a custom adapter to hold the status of checked items(+ different background)):

    public class CABSelection extends ListActivity {
    
        private ArrayList<String> mItems = new ArrayList<String>();
        private SelectionAdapter mAdapter;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            for (int i = 0; i < 24; i++) {
                mItems.add("Name" + i);
            }
            // R.layout.adapters_cabselection_row is a LinearLayout(with green
            // background(#99cc00)) that wraps an ImageView and a TextView
            mAdapter = new SelectionAdapter(this,
                    R.layout.adapters_cabselection_row, R.id.the_text, mItems);
            setListAdapter(mAdapter);
            getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
            getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() {
    
                private int nr = 0;
    
                @Override
                public boolean onCreateActionMode(ActionMode mode, Menu menu) {
                    MenuInflater inflater = getMenuInflater();
                    inflater.inflate(R.menu.cabselection_menu, menu);
                    return true;
                }
    
                @Override
                public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                    return false;
                }
    
                @Override
                public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
                    StringBuilder sb = new StringBuilder();
                    Set<Integer> positions = mAdapter.getCurrentCheckedPosition();
                    for (Integer pos : positions) {
                        sb.append(" " + pos + ",");
                    }               
                    switch (item.getItemId()) {
                    case R.id.edit_entry:
                        Toast.makeText(CABSelection.this, "Edited entries: " + sb.toString(),
                                Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.delete_entry:
                        Toast.makeText(CABSelection.this, "Deleted entries : " + sb.toString(),
                                Toast.LENGTH_SHORT).show();
                        break;
                    case R.id.finish_it:
                        nr = 0;
                        mAdapter.clearSelection();
                        Toast.makeText(CABSelection.this, "Finish the CAB!",
                                Toast.LENGTH_SHORT).show();
                        mode.finish();
                    }
                    return false;
                }
    
                @Override
                public void onDestroyActionMode(ActionMode mode) {
                    nr = 0;
                    mAdapter.clearSelection();
                }
    
                @Override
                public void onItemCheckedStateChanged(ActionMode mode,
                        int position, long id, boolean checked) {
                    if (checked) {
                        nr++;
                        mAdapter.setNewSelection(position, checked);                    
                    } else {
                        nr--;
                        mAdapter.removeSelection(position);                 
                    }
                    mode.setTitle(nr + " rows selected!");
    
                }
    
            });
        }
    
        @Override
        protected void onListItemClick(ListView l, View v, int position, long id) {
            l.setItemChecked(position, !mAdapter.isPositionChecked(position));
        }
    
        private class SelectionAdapter extends ArrayAdapter<String> {
    
            private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
    
            public SelectionAdapter(Context context, int resource,
                    int textViewResourceId, List<String> objects) {
                super(context, resource, textViewResourceId, objects);
            }
    
            public void setNewSelection(int position, boolean value) {
                mSelection.put(position, value);
                notifyDataSetChanged();
            }
    
            public boolean isPositionChecked(int position) {
                Boolean result = mSelection.get(position);
                return result == null ? false : result;
            }
    
            public Set<Integer> getCurrentCheckedPosition() {
                return mSelection.keySet();
            }
    
            public void removeSelection(int position) {
                mSelection.remove(position);
                notifyDataSetChanged();
            }
    
            public void clearSelection() {
                mSelection = new HashMap<Integer, Boolean>();
                notifyDataSetChanged();
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View v = super.getView(position, convertView, parent);//let the adapter handle setting up the row views
                v.setBackgroundColor(Color.parseColor("#99cc00")); //default color
                if (mSelection.get(position) != null) {
                    v.setBackgroundColor(Color.RED);// this is a selected position so make it red
                }
                return v;
            }
    
        }
    
    }
    

    The R.layout.adapters_cabselection_row is a custom layout for the row(a very simple one) with a green background:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#99cc00" >
    
        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher" />
    
        <TextView
            android:id="@+id/the_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="#ffffff"
            android:textSize="17sp"
            android:textStyle="bold" />
    
    </LinearLayout>
    

    R.menu.cabselection_menu is a menu file with 3 options(edit, delete, finish the CAB) which don't do anything except pop a Toast with a message regarding the rows selected:

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <item
            android:id="@+id/edit_entry"
            android:icon="@android:drawable/ic_menu_edit"
            android:title="Edit!"/>
        <item
            android:id="@+id/delete_entry"
            android:icon="@android:drawable/ic_menu_delete"
            android:title="Delete!"/>
        <item
            android:id="@+id/finish_it"
            android:icon="@android:drawable/ic_menu_crop"
            android:title="Get me out!"/>
    
    </menu>
    
    0 讨论(0)
  • 2020-11-28 22:37

    Using ActionBarSherlock the MultiChoiceModeListener used in Luksprog´s answer is not yet available if you want to support API level < 11.

    A workaround is to use the onItemClickListener.

    List setup:

    listView = (ListView) timeline.findViewById(android.R.id.list);
    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
    listView.setItemsCanFocus(false);
    listView.setAdapter(new ListAdapter(getActivity(), R.layout.cleaning_list_item, items));
    

    Listener of ListFragment or ListActivity:

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        SparseBooleanArray checked = listView.getCheckedItemPositions();
        boolean hasCheckedElement = false;
        for (int i = 0; i < checked.size() && !hasCheckedElement; i++) {
            hasCheckedElement = checked.valueAt(i);
        }
    
        if (hasCheckedElement) {
            if (mMode == null) {
                mMode = ((SherlockFragmentActivity) getActivity()).startActionMode(new MyActionMode());
                mMode.invalidate();
            } else {
                mMode.invalidate();
            }
        } else {
            if (mMode != null) {
                mMode.finish();
            }
        }
    }
    

    Where MyActionMode is an implementation of ActionMode.Callback:

    private final class MyActionMode implements ActionMode.Callback { /* ... */ }
    
    0 讨论(0)
  • 2020-11-28 22:41

    I think the easiest way is to apply

    android:background="android:attr/activatedBackgroundIndicator"

    To which ever layout is the one you will be clicking.

    This highlights the layout when selected using

    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    

    worked for me anyway

    0 讨论(0)
提交回复
热议问题