11

通常は。であるListViewがありsingleChoice choiceModeます。ユーザーがアイテムを長押しすると、複数のアイテムを選択できるアクションモードに入り、選択したアイテムに対してアクションを実行できるようにします。

モードになるように構成することListViewsingleChoiceでき、ユーザーはリストアイテムを選択して、その横に詳細フラグメントを表示し、リストアイテム自体をアクティブな状態で表示することができます。

また、アイテムを長押ししてアクションモードを開始し、複数の選択を許可するように構成することもできますListViewが、ListViewは通常モード(アクションモードなし)で単一の選択を許可しません。multipleChoiceModal choiceMode

ListViewをモードにして、アイテムが長押しされたときsingleChoiceにモードに移行するにはどうすればよいですか?multipleChoiceModal

これは私が思いついた最も近いものです:

  1. ListViewをsingleChoiceモードに設定します
  2. ListViewOnItemLongClickListenerとそのリスナーを 設定します。
    1. ListViewOnItemLongClickListenerをに設定しますnull
    2. ListViewchoiceModeをに設定しますmultipleChoiceModal
    3. view.performClick()長押しされたアイテムを呼び出します。

このアプローチにはいくつかの問題があります。

  1. アクションモードは、アイテムを2回長押しするまで開始されません。
  2. 呼び出すとgetListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);、そのメソッドがアクションモードも破棄しようとするため、onDestroyActionMode取得します(ただし、破棄からはまだ戻っていません)。java.lang.StackOverflowError
4

2 に答える 2

6

私がグーグルできるクリーンでシンプルな解決策がないので、この選択モードの切り替えは本当に厄介なようでした。HFM(信仰の人がいる)とKISS(単純な愚かさを保つ)が助けになりました;)

1.シングルモードの選択で開始し、すべてのリスナーを設定します(これはリストアダプターを設定した場所で行われます)

listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 
listView.setOnItemLongClickListener(liListener);
listView.setMultiChoiceModeListener(mcListener);

2.選択モードを切り替えるためのインターフェースを実装します。それを機能させるための秘訣は、実装の外で単一選択モードに戻すことです。つまり、アクションモードを破棄した後です。したがって、単純なフラグを使用してCABの破棄をマークするだけです。もう1つのトリックは、選択モードが有効になるまでの時間を確保するために、falseonItemLongClickを返すことです。

private OnItemLongClickListener liListener = new OnItemLongClickListener() {
        @Override
        public boolean onItemLongClick(AdapterView<?> parent, View view,
                int position, long id) {                
            listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
            isCABDestroyed = false;                 
            return false; // so this action does not consume the event!!!
        }
    };

private MultiChoiceModeListener mcListener = new MultiChoiceModeListener() {
    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position,
                                          long id, boolean checked) {
        final int checkedCount = listView.getCheckedItemCount();
        switch (checkedCount) {
            case 0:
                mode.setSubtitle(null);
                break;
            case 1:
                mode.setSubtitle("One item selected");
                break;
            default:
                mode.setSubtitle("" + checkedCount + " items selected");
                break;
        }
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.delete:
                //do your action command here
                mode.finish();
                return true;
            default:
                return false;
        }
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.context_menu, menu);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        isCABDestroyed = true; // mark readiness to switch back to SINGLE CHOICE after the CABis destroyed  

    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false;
    }
};

3.これがスイッチバックです

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);  
        if(isCABDestroyed) {
            listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
            //do your action command  here
        }
        l.setItemChecked(position, true);

    }
于 2012-05-05T15:39:08.047 に答える
3

私は自分のプログラムの1つでこれを使用しました

私たちListView.CHOICE_MODE_MULTIPLE_MODAL当時lv.setMultiChoiceModeListener(new ModeCallBack());

    public class ModeCallBack implements ListView.MultiChoiceModeListener{

    View mSelectView;
    TextView mSelectedCount;
    ArrayList<Long> mCheckedItems;

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getActivity());
        SharedPreferences.Editor edit = pref.edit();

        if(item.getItemId() == R.id.bowler_delete){

            for(int i=0; i<mCheckedItems.size(); i++){
                long id = mCheckedItems.get(i);

                getActivity().getContentResolver().delete(BowlersDB.CONTENT_URI,BowlersDB.ID+"="+id,null);
            }
        }else if(item.getItemId() == R.id.bowler_add_ball){
            if(mCheckedItems.size() > 1){
                Toast.makeText(getActivity(),"Can only add bowling balls to one bowler at a time",Toast.LENGTH_SHORT).show();
            }else{
                edit.putLong(Preferences.BOWLER_SELECTED_FOR_BALL,mCheckedItems.get(0)).commit();

                ListFragment lf = new ManufacturersList();
                FragmentTransaction ft;
                ft = getFragmentManager().beginTransaction();
                ft.replace(R.id.frameOne, lf).addToBackStack(null).commit();
                //mRemover.rFragment();
            }
        }else if(item.getItemId() == R.id.add_bowler_to_team){
            for(int i=0; i<mCheckedItems.size(); i++){

                long id = mCheckedItems.get(i);
                ContentValues values = new ContentValues();
                values.put(TeamBowlers.BOWLER_ID,id);
                values.put(TeamBowlers.TEAM_ID,pref.getLong(Preferences.TEAM_SELECTED,1));
                getActivity().getContentResolver().insert(TeamBowlers.CONTENT_URI, values);

            }
            FragmentManager fm = getFragmentManager();
            fm.popBackStack();
        }
        mode.finish();
        return true;
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        MenuInflater inflate = getActivity().getMenuInflater();
        if(fromTeam){
            inflate.inflate(R.menu.bowlers_team_action_menu, menu);
        }else{
            inflate.inflate(R.menu.bowler_action_menu, menu);
        }
        if(mSelectView == null){
            mSelectView = (ViewGroup)LayoutInflater.from(getActivity()).inflate(R.layout.select_count_layout,null);

            mSelectedCount = (TextView)mSelectView.findViewById(R.id.count_tv);

        }
        if(mCheckedItems == null){
            mCheckedItems = new ArrayList<Long>();
        }
        mode.setCustomView(mSelectView);
        return true;
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mCheckedItems = null;

    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        if(mSelectView == null){
            mSelectView = (ViewGroup)LayoutInflater.from(getActivity()).inflate(R.layout.select_count_layout,null);

            mSelectedCount = (TextView)mSelectView.findViewById(R.id.count_tv);
        }

        if(mCheckedItems == null){
            mCheckedItems = new ArrayList<Long>();
        }
        return true;
    }

    @Override
    public void onItemCheckedStateChanged(ActionMode mode, int position,long id, boolean checked) {         

        final int count = lv.getCheckedItemCount();
        mSelectedCount.setText(String.valueOf(count));
        if(checked){
            mCheckedItems.add(id);
        }else{
            mCheckedItems.remove(id);
        }
    }

}

これにより、単一選択の単一リストビュークリックとロングクリックの複数選択が可能になります。これはすべてICSメッセージングアプリから取得されたため、閲覧することもできます

于 2012-04-20T18:24:18.660 に答える