29

何日も読んで試行錯誤した後、私はあきらめて助けを求めています。

< 編集 > 私は ActionBarSherlock を使用しています。< /編集 >

私が達成したいこと: ユーザーが複数のリスト項目を選択できる、各行のカスタム レイアウトを持つ ListView。選択したリスト項目は、異なる背景色にする必要があります。少なくとも 1 つのアイテムが選択されている場合、コンテキスト アクション バー (CAB) が表示されます。これは、GMail アプリでメールを複数選択するのとほぼ同じように見えるはずです。唯一の違いは、gmail アプリでは、行のチェックボックスをクリックすることで選択が行われるのに対し、チェックボックスは必要ありませんが、ユーザーがどこをクリックしても行を選択する必要があることです。 Gmail アプリでの複数選択

私が試したこと:このチュートリアル に従って、チェック状態が切り替えられたときに背景色を変更するロジックを備えたチェック可能な行レイアウトを使用すると、ListViewでOnItemClickListenerのようなクリックリスナーを登録してCABを表示できなかったことを除いて、すべてが機能しました. 選択したアイテムの背景色を変更できなかったため、各行ビューにクリックリスナーを提供することは役に立ちませんでした。私もそのような ListView に MultiChoiceModeListener を追加しようとしました

    listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
    listView.setMultiChoiceModeListener(new MultiChoiceModeListener() { //.. });

同じ結果で、背景色は変わりません。

私が探しているもの:これを行う方法のヒントまたはチュートリアルまたはサンプルコード。役立つコード スニペットが必要な場合は、お知らせください。

4

3 に答える 3

37

コードが役立つかどうかを確認してください(基本的に、ListActivityチェックされたアイテムのステータスを保持するためのカスタムアダプターを使用しています(+異なる背景)):

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

    }

}

これR.layout.adapters_cabselection_rowは、緑色の背景を持つ行のカスタム レイアウト (非常に単純なもの) です。

<?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_menuToast3 つのオプション (編集、削除、CAB の終了) を含むメニュー ファイルで、選択された行に関するメッセージを表示する以外は何もしません。

<?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>
于 2012-05-15T10:13:34.910 に答える
14

申し込むのが一番簡単だと思います

android:background="android:attr/activatedBackgroundIndicator"

クリックするレイアウトはどれですか。

を使用して選択すると、レイアウトが強調表示されます。

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);

とにかく私のために働いた

于 2013-01-02T11:08:48.663 に答える
11

APIレベル11未満をサポートしたい場合、Luksprogの回答で使用されているActionBarSherlockをMultiChoiceModeListener使用することはまだ利用できません。

回避策は、onItemClickListener を使用することです。

リストの設定:

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

ListFragment または 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();
        }
    }
}

MyActionMode は ActionMode.Callback の実装です。

private final class MyActionMode implements ActionMode.Callback { /* ... */ }
于 2012-05-21T08:51:50.933 に答える