2010-10-22 52 views
26

Ứng dụng có ListView với nhiều lựa chọn được bật, trong giao diện người dùng hoạt động như mong đợi. Nhưng khi tôi đọc các giá trị bằng cách sử dụng mã này:Tại sao ListView.getCheckedItemPositions() không trả lại giá trị chính xác?

Log.i(TAG,"Entered SearchActivity.saveCategoryChoice()"); 
SparseBooleanArray checkedPositions = categorySelector.getCheckedItemPositions(); 
Log.i(TAG,"checkedPositions: " + checkedPositions.size()); 

if (checkedPositions != null) { 
    int count = categoriesAdapter.getCount(); 
    for (int i=0;i<count;i++) { 
    Log.i(TAG,"Selected items: " + checkedPositions.get(i)); 
    } 
} 

tôi nhận được kết quả này, không có vấn đề gì nhà nước mỗi hộp kiểm là:

Entered SearchActivity.saveCategoryChoice() 
checkedPositions: 0 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 
Selected items: false 

Các SparseBooleanArray dường như return false cho bất kỳ không tồn tại mục, do đó, nguồn gốc của các vấn đề có vẻ là getCheckedItemPositions() trả về một mảng trống. Phương thức này hoạt động như thể không có mục nào trong ListView, nhưng có.

tôi có thể nhìn thấy từ các tài liệu mà không có giá trị được trả về khi ListView không được thiết lập như nhiều lựa chọn, nhưng nó là, sử dụng câu lệnh:

categorySelector.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 

Trong kịch bản của tôi, adapter tôi m sử dụng là một phân lớp của ArrayAdapter, và (không có bất kỳ bằng chứng vững chắc) Tôi nghi ngờ điều này có thể là nguyên nhân, mặc dù tôi không thể nhìn thấy lý do tại sao nó không nên làm việc.

Trả lời

4

Tôi vẫn không biết tại sao, nhưng trong trường hợp của tôi, getCheckedItemPositions() trả về giá trị sai cho tất cả các mục. Tôi không thể nhìn thấy một cách để sử dụng các phương pháp trên ListView để có được các giá trị boolean ra. Đối tượng SparseBooleanArray dường như không có dữ liệu trong thế giới thực. Tôi nghi ngờ điều này có thể là do một số quirk của việc thực hiện của tôi, có lẽ tôi đã phân lớp ArrayAdapter. Đó là bực bội, các vấn đề như thế này là một cống thời gian thực.

Dù sao, giải pháp tôi đã sử dụng là để đính kèm trình xử lý cho từng Hộp kiểm riêng lẻ dưới dạng hàng ListView được tạo. Vì vậy, từ ListView.getView() Tôi gọi phương thức này:

private void addClickHandlerToCheckBox(CheckBox checkbox) { 
    checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() { 
     public void onCheckedChanged(CompoundButton arg0, boolean arg1) { 
     CheckBox checkbox = (CheckBox)arg0; 
     boolean isChecked = checkbox.isChecked(); 
     // Store the boolean value somewhere durable 
     } 
    }); 
} 
+0

Bạn có thể giải thích cách thêm addClickHandlerToCheckBox cho mỗi hộp kiểm trong danh sách hộp kiểm của mình không? cảm ơn. – rayman

+0

Có thể vấn đề là khung nhìn được trả về từ getView của adapter() đã không thực hiện giao diện Checkable. – Sergey

+0

Tôi gặp vấn đề tương tự, nhưng do sự lựa chọn bị xóa bởi hộp thoại xác nhận. Bạn cần sao chép 'SparseBooleanArray' trước khi xóa các trạng thái đã chọn (tự động). – jtooker

0

Không có sự khác biệt cơ bản giữa 'selected''checked'?

Nghi ngờ bạn muốn setItemChecked() từ một OnItemSelectedListener ...

+0

Bạn nói đúng là tôi đã kiểm tra và chọn lén trong câu hỏi của tôi một chút, nhưng ... các tài liệu cho getCheckedItemPositions() làm nhà nước rằng chế độ lựa chọn phải được nhiều hoặc nó trả về null. Tôi cũng đã thử getCheckItemIds() và cũng trả về một bộ sưu tập trống. Tôi nghi ngờ tôi sẽ kết thúc bằng cách sử dụng một người nghe, nhưng tôi tò mò muốn hiểu lý do tại sao các phương pháp không hoạt động trực giác. –

+0

Có, đó là một chút bối rối tại sao họ làm cho chế độ lựa chọn có liên quan ở tất cả. Nhìn qua ListView.java vừa rồi, có vẻ như với tôi rằng trừ khi bạn gọi setItemChecked(), tôi không nghĩ rằng bạn sẽ nhận được trạng thái tự động kiểm tra là bạn (khá hợp lý) giả sử sẽ xảy ra khi mục được chọn. Trạng thái kiểm tra tự động duy nhất mà tôi có thể thấy xảy ra khi các mục danh sách được thêm vào, và chỉ sau đó nếu lớp View-derived của bạn thực thi Checkable. Nó sẽ là tốt nếu xử lý lựa chọn mặc định đã làm điều tương tự ... –

+0

Tôi cho rằng có ý nghĩa, nhưng vẫn khá khó hiểu. Nếu tôi có một ListView nhiều lựa chọn với các hộp kiểm và có một phương thức gọi là getCheckedItemIds() thì có vẻ hợp lý để giả sử nó sẽ cung cấp trạng thái. Nhưng tôi đã reimplemented nó bằng cách sử dụng một handler trên OnCheckedChangeListener và đó là làm việc tốt, trong thực tế, bằng cách sử dụng getTag() đó là một cách tiếp cận tốt đẹp và sạch sẽ. Cảm ơn cậu vì đã chia sẻ những suy nghĩ của mình. –

6

Tôi nhớ có một vấn đề với điều này bản thân mình một khi trở lại. Here là câu hỏi trước của tôi, không liên quan trực tiếp đến vấn đề của bạn, nhưng chứa một số mã có thể hữu ích. Những gì bạn có thể muốn thử đang sử dụng checkedPositions.valueAt(int index) thay vì checkedPositions.get(int index). Tôi nghĩ rằng đó có thể là những gì bạn đang thực sự tìm kiếm.

+0

Tôi vừa thử sử dụng valueAt() và đối với tôi, vì bất kỳ lý do gì, nó trả về false cho tất cả chúng, bất kể các hộp kiểm được đặt là gì. –

0

Điều chỉnh này đã sửa nó cho tôi. Thay đổi phương thức getView để "vị trí int" là "vị trí int cuối cùng". Sau đó, làm điều này với hộp kiểm của bạn:

Hãy để tôi giải thích. danh sách là một tham chiếu đến listview và trong trường hợp của tôi adapter là một lớp bên trong trong hộp thoại giữ danh sách.

0

Tôi tìm thấy chủ đề này bằng cách có cùng một vấn đề nhưng tôi nghĩ rằng tôi đã đưa ra một giải pháp thay thế cho tôi vì những lý do không rõ. Bất cứ khi nào tôi cố gắng nhận được một giá trị tôi đã không có gì, nhưng nếu tôi vòng lặp thông qua các thiết lập danh sách tất cả để sai nó bắt đầu làm việc giống như dự định.

Đây thực sự là một tính năng mà tôi đã triển khai khi người dùng có thể chọn "Chọn tất cả" hoặc "Bỏ chọn tất cả". Tôi chạy phương thức này trong onCreate của tôi.

private void selectNone() { 
    ListView lv = getListView(); 
    for (int i = 0; i < lv.getCount(); i++) { 
     lv.setItemChecked(i, false); 
    } 
} 

Bây giờ tất cả các giá trị của tôi là chính xác. Để nhận được các giá trị, trong trường hợp của tôi, chỉ cần Strings.

private void importSelected() {  
    ListView lv = getListView(); 
    SparseBooleanArray selectedItems = lv.getCheckedItemPositions(); 

    for (int i = 0; i < selectedItems.size(); i++) { 
     if (selectedItems.get(i)) { 
      String item = lv.getAdapter().getItem(selectedItems.keyAt(i)).toString(); 
     } 
    } 

    selectNone(); //Reset 
} 

Tôi hy vọng điều này sẽ giúp ai đó.

1

Không ai trong số các giải pháp trên đã làm việc cho tôi, thay vào đó tôi có được mọi trẻ em (một checkedTextView) từ ListView và xem nếu nó được kiểm tra hay không:

  ListView myListView = myViewActivity.getListView(); 
     ArrayList<String> selectedChildren2 = new ArrayList<String>(); 

     for(int i = 0;i<myListView.getChildCount();i++) 
     { 
      CheckedTextView c = (CheckedTextView) myListView.getChildAt(i); 
      if(c.isChecked()) 
      { 
       String child = c.getText().toString(); 
       selectedChildren.add(child); 
       } 
     } 
+0

Cảm ơn bạn. Chỉ có điều này thực sự làm việc cho tôi. –

+0

Điều này sẽ không hoạt động nếu bạn có nhiều phần tử hơn hiển thị vì nó chỉ lặp qua các hàng hiển thị. –

46

kcoppock là đúng, bạn cần phải sử dụng valueAt(), mã làm việc nên

SparseBooleanArray checkedItems = categorySelector.getCheckedItemPositions(); 
if (checkedItems != null) { 
    for (int i=0; i<checkedItems.size(); i++) { 
     if (checkedItems.valueAt(i)) { 
      String item = categorySelector.getAdapter().getItem(
            checkedItems.keyAt(i)).toString(); 
      Log.i(TAG,item + " was selected"); 
     } 
    } 
} 
0

tôi cũng sử dụng các giải pháp gyller cho thấy liên quan đến "khởi xướng" listview

ListView lv = getListView(); for (int i = 0; i < lv.getCount(); i++) { lv.setItemChecked(i, false); }

trước khi gọi getCheckItemPositions() và ngừng sản xuất kết quả sai!

2

Điều này xảy ra nếu bạn không chọn đúng tài nguyên để hiển thị các mục khác nhau của mình. Nó hoạt động tốt nếu bạn chọn tài nguyên có sẵn android.R.layout.simple_list_item_multiple_choice. Phương pháp getCheckedItemPositions được kết hợp theo cách nào đó với tài nguyên được tích hợp sẵn.

0

trong khi tôi không tin rằng tôi đã cố gắng mọi biến thể mô tả ở đây, đây là một trong đó đã làm việc cho tôi :)

 @Override 
     public View getView(final int position, View convertView, ViewGroup parent) 
     { 

      CheckedTextView retView = (CheckedTextView) convertView; 
... 
      retView.setOnClickListener(new View.OnClickListener() 
      { 
       public void onClick(View v) 
       { 
        CheckedTextView chkVw = (CheckedTextView) v; 
//     chkVw.toggle(); 
//     chkVw.setChecked(!chkVw.isChecked()); 
        mLstVwWordingSets.setItemChecked(position + 1, !chkVw.isChecked()); 
       } 
      }); 
... 
     } 

Và sau

 SparseBooleanArray checkedItemsArray = mLstVwWordingSets.getCheckedItemPositions(); 
     for (int i = 1; i < mLstVwWordingSets.getCount(); i++)   //skip the header view 
     { 
      if (checkedItemsArray.get(i, false)) 
       Log.d(_TAG, "checked item: " + i); 
     } 

tôi truy cập vào vị trí + 1 do chế độ xem tiêu đề mà danh sách của tôi đã có sẵn.

HTH

0
ArrayList<Integer> ar_CheckedList = new ArrayList<Integer>(); 

cho mỗi holer của hộp kiểm tra tôi đang sử dụng để lưu trữ nó trong mảng

holder.chk_Allow.setOnCheckedChangeListener(new OnCheckedChangeListener() { 
       public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
        if(isChecked) 
         ar_CheckedList.add(position); 
       } 
      }); 

trên nhấp chuột vào nút của

for (int i = 0; i < ar_CheckedList.size(); i++) 
{ 
     HashMap<String, String> temp=(HashMap<String, String>) contactList.get(ar_CheckedList.get(i)); 
     str_Phone_No=temp.get(TAG_CONTACT_MOBILE); 
     send(str_Phone_No); 
} 
1

Không có nhu cầu để xử lý kiểm tra/bỏ chọn các mục trong ListView. Nó đã tự làm nó.

gì không dường như ghi nhận là các ListView sẽ chỉ làm điều này nếu:

  1. một ListAdapter được thiết lập và
  2. chế độ lựa chọn là CHOICE_MODE_MULTIPLE và
  3. id được sử dụng bởi ListAdapterổn định.

Điểm thứ ba là điều khiến tôi phát điên trong một thời gian.

Tôi không chắc chắn những gì 'ổn định' có nghĩa là (tôi đoán rằng các id không bao giờ thay đổi trong khi danh sách được hiển thị). Theo như các ListView là có liên quan, nó có nghĩa là phương pháp hasStableIds() trong ListAdapter trả về true.

Tôi tạo ra một lớp con đơn giản của ArrayAdapter như thế này:

public class StableArrayAdapter<T> extends ArrayAdapter<T> { 

    public StableArrayAdapter(Context context, int textViewResourceId, List<T> objects) { 
     super(context, textViewResourceId, objects); 
    } 

    @Override 
    public boolean hasStableIds() { 
     return true; 
    } 
} 

(Bạn đã có phân lớp của bạn, vì vậy chỉ cần thêm hasStableIds override)

Tất nhiên, chúng ta cần thêm các nhà xây dựng là một trong những đang sử dụng với ArrayAdapter.

Khi bạn sử dụng lớp này làm ListAdapter, getCheckedItemPositions() hoạt động như mong đợi.

Lưu ý cuối cùng: setChoiceMode phải được gọi SAU KHI đặt bộ điều hợp danh sách.

1

Đây là một chủ đề cũ nhưng vì đây về cơ bản đã đưa ra đầu tiên trong tìm kiếm Google hiện tại đây là một cách nhanh chóng để hiểu những gì listView.getCheckedItemPositions() làm:

Trừ khi danh sách Item không 'toggled' ở tất cả trong ListView của bạn , nó sẽ không được thêm vào SparseBooleanArray được trả lại bởi listView.getCheckedItemPositions()

Nhưng sau đó, bạn thực sự không muốn người dùng của bạn nhấp vào từng mục danh sách để "đúng" thêm nó vào SparseBooleanArray trả về phải không?

Do đó bạn cần phải kết hợp việc sử dụng valueAt()keyAt() của SparseBooleanArray cho việc này.

SparseBooleanArray checkedArray = listView.getCheckedItemPositions(); 

    ArrayList<DataEntry> entries = baseAdapter.getBackingArray(); //point this to the array of your custom adapter 

    if (checkedArray != null) 
    { 
     for(int i = 0; i < checkedArray.size(); i++) 
     { 
      if(checkedArray.valueAt(i)) //valueAt() gets the boolean 
       entries.yourMethodAtIndex(checkedArray.keyAt(i)); //keyAt() gets the key 
     } 
    } 
+0

Vấn đề của tác giả là checkedPositions.size() (checkedArray.size() trong trường hợp của bạn) luôn trả về 0. – Sergey

+1

Câu hỏi lớn là, tại sao kiểm tra không 'SparseBooleanArray checkedArray = listView.getCheckedItemPositions()' clear các mục hiện không được chọn nhưng đã được kiểm tra trong quá khứ! –

0

ArrayList selectedChildren = new ArrayList();

   for(int i = 0;i<list.getChildCount();i++) 
       { 
        CheckBox c = (CheckBox) list.getChildAt(i); 
        if(c.isChecked()) 
        { 
         String child = c.getText().toString(); 
         selectedChildren.add(child); 
        } 
       } 
       Log.i(TAG, "onClick: " + selectedChildren.size()); 
0

chỉ cần vào xml nơi listview của bạn được xác định và thiết lập thuộc tính

**android:choiceMode="multipleChoice"** 

xmlFile tôi

<?xml version="1.0" encoding="utf-8"?> 
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.ali.myapplication.MainActivity"> 

    <ListView 
     android:id="@+id/lvCustomList" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:choiceMode="multipleChoice" 
     /> 

</android.support.constraint.ConstraintLayout> 

và sau đó trong javafile của bạn như: -

SparseBooleanArray checked=lvDetail.getCheckedItemPositions(); 
for (int i = 0; i < lvDetail.getAdapter().getCount(); i++) { 
if (checked.get(i)) {    
      Toast.makeText(getApplicationContext(),checked.get(i),Toast.LENGTH_SHORT).show();   

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