2012-05-15 39 views
28

Sau khi đọc và thử lại trong nhiều ngày, tôi sẽ từ bỏ và yêu cầu trợ giúp.Nhiều lựa chọn trong Chế độ xem danh sách tùy chỉnh với CAB

< chỉnh sửa> Tôi đang sử dụng ActionBarSherlock. </chỉnh sửa>

Những gì tôi muốn đạt được: Một ListView với một bố trí tùy chỉnh cho mỗi hàng, nơi người dùng có thể chọn nhiều mục danh sách. Mục danh sách đã chọn phải có màu nền khác. Khi có ít nhất một mục được chọn, một thanh hành động theo ngữ cảnh (CAB) sẽ được hiển thị. Nó sẽ giống như nhiều lựa chọn email trong ứng dụng Gmail. Sự khác biệt duy nhất là trong ứng dụng gmail, lựa chọn được thực hiện bằng cách nhấp vào hộp kiểm của một hàng, trong khi tôi không muốn có hộp kiểm, nhưng một hàng nên được chọn không có vấn đề, nơi người dùng nhấp chuột. Multiple selection in GMail app

gì tôi đã cố gắng: Sau this tutorial, sử dụng một cách bố trí hàng Checkable với một số logic để thay đổi màu nền khi trạng thái séc được toggled, tôi có tất cả mọi thứ làm việc ngoại trừ việc tôi không thể đăng ký một người biết lắng nghe nhấp chuột như OnItemClickListener trên ListView để hiển thị CAB. Không cung cấp trình nghe nhấp chuột cho mỗi hàng Chế độ xem đã giúp vì điều này đã ngăn thay đổi màu nền của các mục đã chọn. Tôi cũng đã cố gắng thêm một MultiChoiceModeListener vào ListView như thế

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

Với cùng một kết quả, không có sự thay đổi màu nền.

Điều tôi đang tìm kiếm: Một gợi ý hoặc hướng dẫn hoặc mã mẫu làm cách nào để thực hiện việc này. Nếu bạn cần một số đoạn mã để trợ giúp, hãy cho tôi biết.

+1

Tôi đã chỉnh sửa câu trả lời của tôi, mã của tôi nên làm những gì bạn muốn (nếu tôi hiểu yêu cầu của bạn). – Luksprog

+0

Liên kết hướng dẫn đã chết. Bạn có thể sửa nó không? – RHaguiuda

Trả lời

11

Sử dụng ActionBarSherlock các MultiChoiceModeListener sử dụng trong Luksprog's Câu trả lời là chưa có sẵn nếu bạn muốn hỗ trợ mức API < 11.

Một cách giải quyết là sử dụng onItemClickListener.

Danh sách thiết lập:

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 của ListFragment hoặc 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(); 
     } 
    } 
} 

đâu MyActionMode là một thực hiện ActionMode.Callback:

private final class MyActionMode implements ActionMode.Callback { /* ... */ } 
+0

Bạn nên đề cập đến bạn sử dụng 'ActionBarSherlock' tôi có thể đưa ra câu trả lời tương tự. Ngay cả trong ví dụ của tôi (với 'MultiChoceiListener' có sẵn), bạn có thể thực hiện cá thể' ActionMode' của riêng bạn để khởi động CAB. – Luksprog

+0

Vâng, đó là lỗi của tôi. Tôi không nghĩ rằng đó là tầm quan trọng khi tôi đăng câu hỏi. Nhưng tôi khá chắc chắn rằng câu trả lời của bạn sẽ giúp những người khác sử dụng API cấp 11 trở lên. – Konsumierer

+0

Trong ví dụ mã này; ý nghĩa của "ListAdapter mới" là gì? ListAdapter là trừu tượng. Mã có chỉ để tạo một điểm không? Chữ ký trông hơi giống ArrayAdapter. Nó là một lỗi đánh máy? –

36

Xem nếu mã giúp bạn (đó là cơ bản một ListActivity với một adapter tùy chỉnh để giữ trạng thái các mục kiểm tra (+ nền khác nhau)):

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

    } 

} 

Các R.layout.adapters_cabselection_row là một cách bố trí tùy chỉnh cho hàng (một rất đơn giản) với một nền màu xanh lá cây:

<?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 là một file menu với 3 lựa chọn (chỉnh sửa, xóa, hoàn thành CAB) mà không làm bất cứ điều gì ngoại trừ bật một Toast với một thông điệp liên quan đến các hàng sel ected:

<?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

Tôi không thể xác minh rằng đây là câu trả lời đúng, vì tôi quên đề cập đến việc tôi đang sử dụng ActionBarSherlock. MultiChoiceModeListener chỉ khả dụng kể từ cấp API 11 và ABS chưa triển khai tương đương. Nhưng câu trả lời trước đây của bạn dường như giúp tôi. – Konsumierer

+0

Hoạt động rất tốt với API = 11 trở lên nhưng không hỗ trợ API <11. Có thư viện hỗ trợ nào không? – Apurva

+0

@Apurva Một 'MultiChoiceModeListener' là một phần bổ sung ở trên cùng của' ActionMode' cơ bản. Nếu bạn muốn thực hiện chức năng trên các phiên bản dưới đây, bạn có thể chỉ cần thực hiện 'ActionMode' của riêng mình và nối nó với các sự kiện' ListView'. Câu trả lời của Konsumierer dưới đây cho thấy cách bạn có thể làm điều đó. – Luksprog

12

Tôi nghĩ rằng cách dễ nhất là để áp dụng

android:background="android:attr/activatedBackgroundIndicator"

Để trong đó bao giờ bố trí là một trong những bạn sẽ được nhấn.

này nhấn mạnh cách bố trí khi lựa chọn sử dụng

listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL); 

làm việc cho tôi anyway

+1

là có sẵn ngay cả đối với các phiên bản trước tổ ong không? –

+0

Trình chỉnh sửa chỉ cho tôi thấy lỗi: "lỗi: Lỗi: Các loại chuỗi không được phép (tại 'nền' có giá trị 'android: attr/ activatedBackgroundColor')." – faizal

+3

Vì định dạng đúng là '? Android: attr/activatedBackgroundIndicator' Và không, định dạng của nó không dành cho phiên bản trước tổ ong, đây chỉ là cho API 11+ – Sandak

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