2012-04-20 15 views
8

Tôi có một ListView thông thường là singleChoicechoiceMode. Khi người dùng nhấn lâu vào một mục, tôi muốn nhập một chế độ hành động cho phép chọn nhiều mục để họ có thể thực hiện một hành động trên bất kỳ mục nào đã chọn.Thay đổi ListView choiceMode từ singleChoice thành multipleChoiceModal

Tôi có thể định cấu hình ListView sao cho ở chế độ singleChoice và người dùng có thể chọn mục danh sách để hiển thị đoạn chi tiết bên cạnh và tự hiển thị mục danh sách ở trạng thái được kích hoạt.

Tôi cũng có thể cấu hình các ListView để nó trong multipleChoiceModalchoiceMode và thực hiện một nền báo chí dài trên một mục khởi động chế độ hoạt động và cho phép nhiều lựa chọn, nhưng bây giờ ListView sẽ không cho phép một sự lựa chọn duy nhất trong bình thường chế độ (không có chế độ hành động).

Làm cách nào để có một ListView ở chế độ singleChoice và sau đó chuyển sang chế độ multipleChoiceModal khi một mục được nhấn lâu?

này là gần nhất tôi đã có thể đưa ra:

  1. thiết lập các ListView sang chế độ singleChoice
  2. thiết lập các ListView của OnItemLongClickListener và người nghe rằng:
    1. thiết lập các ListView của OnItemLongClickListener đến null
    2. đặt ListView's choiceMode thành multipleChoiceModal
    3. gọi view.performClick() trên mặt hàng đã được nhấn lâu.

Phương pháp này có một vài vấn đề.

  1. Chế độ tác vụ không được bắt đầu cho đến lần thứ hai tôi nhấn lâu vào một mục.
  2. Khi tôi gọi getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE); trong onDestroyActionMode Tôi nhận được java.lang.StackOverflowError vì phương pháp đó kết thúc bằng việc cố gắng hủy chế độ tác vụ (nhưng chúng tôi chưa được trả lại từ tiêu hủy).
+0

gì sẽ xảy ra sau khi bạn nhập multipleChoiceMode, chọn 2 và quay trở lại singleCheckMode? – user387184

Trả lời

3

tôi đã sử dụng này trong một trong những chương trình của tôi

chúng ta ListView.CHOICE_MODE_MULTIPLE_MODAL sau đó 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); 
     } 
    } 

} 

này cho phép lựa chọn đơn đơn listview nhấp chuột và nhiều lựa chọn bấm dài. Tất cả điều này đã được rút khỏi ứng dụng nhắn tin ICS để bạn có thể duyệt qua đó quá

+0

Có lẽ tôi đang thiếu một cái gì đó, nhưng làm thế nào để danh sách đi vào singleChoiceMode sau khi chế độ hành động bị phá hủy? –

+0

chỉ ghi đè lên 'onListItemClick' trong listview sau đó khi người dùng nhấp vào mục trong listview hiển thị đoạn liên quan đến nhấp chuột. trừ khi tôi đang thiếu cái gì ở đây? – tyczj

+0

Tôi đoán phần mà tôi không đề cập đến là các mục trong danh sách của tôi tận dụng lợi thế của state_activated. state_activated chỉ được đặt thành true khi mục được chọn thực sự là một lựa chọn trong chế độ singleChoice, vì vậy tôi thực sự muốn ListView của mình thay đổi trở lại chế độ singleChoice. –

5

Nó thực sự có vẻ khó xử lý chuyển đổi chế độ lựa chọn này vì không có giải pháp đơn giản và sạch nào mà tôi có thể google. HFM (có niềm tin người đàn ông) và KISS (giữ nó đơn giản ngu ngốc) giúp;)

1.Start trong sự lựa chọn chế độ single và thiết lập tất cả các thính giả (điều này được thực hiện, nơi bạn thiết lập các bộ chuyển đổi danh sách)

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

2.thực hiện các giao diện để chuyển đổi giữa các chế độ lựa chọn. Các TRICK để làm cho nó hoạt động là để chuyển trở lại chế độ lựa chọn duy nhất bên ngoài việc thực hiện, có nghĩa là SAU KHI bạn phá hủy chế độ hành động !! Vì vậy, chỉ cần sử dụng một lá cờ đơn giản để đánh dấu sự hủy diệt CAB. Một TRICK khác là trả về false onItemLongClick để chế độ lựa chọn có thời gian để có hiệu lực.

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.Here là việc chuyển đổi trở lại

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

    } 
+0

Xin lỗi để mang lại một bài cũ nhưng tôi đã thử cách mô tả ở trên nhưng các mục listView của tôi không được đánh dấu màu xanh (như trên whatsapp). Làm thế nào tôi có thể làm điều đó xảy ra? Cảm ơn ! – Leonardo

+0

Nếu giao diện người dùng yêu cầu điều hướng và quay trở lại thông qua giải trí (ví dụ: khi giao diện người dùng dựa trên Fragment), đừng quên chuyển trạng thái ListView thành 'ListView.CHOICE_MODE_SINGLE' nếu nó nằm trong' ListView.CHOICE_MODE_MULTIPLE_MODAL' vào thời điểm biến mất. Ngoài ra, giữ cho diring lựa chọn chuyển từ MULTI sang SINGLE. Tôi làm như sau: nếu (! IsCABDestroyed) { \t int selection = contentList.getCheckedItemPositions(). KeyAt (0); \t contentList.setChoiceMode (ListView.CHOICE_MODE_SINGLE); \t contentList.setItemChecked (lựa chọn, đúng); } // thực hiện điều hướng – StAlex

Các vấn đề liên quan