2012-02-22 31 views
8

Sự cố này được thảo luận trong câu hỏi này Android: Wrong item checked when filtering listview. Để tóm tắt vấn đề, khi sử dụng một listview với một CursorAdapter và một bộ lọc, các mục được chọn trong danh sách lọc sẽ mất lựa chọn của chúng sau khi bộ lọc bị xóa và thay vào đó, các mục tại vị trí đó trong danh sách chưa được lọc sẽ được chọn.Triển khai chế độ xem danh sách với nhiều lựa chọn có bộ lọc bằng Bộ chuyển đổi con trỏ

Sử dụng mẫu mã trong câu hỏi được liên kết ở trên, nơi chúng tôi nên đặt mã để đánh dấu các hộp kiểm. Tôi tin rằng nó nên có trong phương thức getView() của CustomCursorAdapter, nhưng tôi không chắc chắn. Ngoài ra, làm thế nào để chúng ta truy cập HashSet giữ tất cả các selectIds trong lớp adapter tùy chỉnh, bởi vì nó sẽ được khởi tạo và sửa đổi trong hoạt động chính đang giữ danh sách.

hoạt động của tôi thực hiện ListView

@Override 
public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.selectfriends); 

     Log.v(TAG, "onCreate called") ; 

     selectedIds = new ArrayList<String>() ; 
     selectedLines = new ArrayList<Integer>() ; 

     mDbHelper = new FriendsDbAdapter(this); 
     mDbHelper.open() ; 

     Log.v(TAG, "database opened") ; 

     Cursor c = mDbHelper.fetchAllFriends(); 
     startManagingCursor(c); 

     Log.v(TAG, "fetchAllFriends Over") ; 


     String[] from = new String[] {mDbHelper.KEY_NAME}; 
     int[] to = new int[] { R.id.text1 }; 

     final ListView listView = getListView(); 
     Log.d(TAG, "Got listView"); 

    // Now initialize the adapter and set it to display using our row 
     adapter = 
      new FriendsSimpleCursorAdapter(this, R.layout.selectfriendsrow, c, from, to); 

     Log.d(TAG, "we have got an adapter"); 
    // Initialize the filter-text box 
    //Code adapted from https://stackoverflow.com/questions/1737009/how-to-make-a-nice-looking-listview-filter-on-android 

     filterText = (EditText) findViewById(R.id.filtertext) ; 
     filterText.addTextChangedListener(filterTextWatcher) ; 

    /* Set the FilterQueryProvider, to run queries for choices 
    * that match the specified input. 
    * Code adapted from https://stackoverflow.com/questions/2002607/android-how-to-text-filter-a-listview-based-on-a-simplecursoradapter 
    */ 

     adapter.setFilterQueryProvider(new FilterQueryProvider() { 
      public Cursor runQuery(CharSequence constraint) { 
       // Search for friends whose names begin with the specified letters. 
       Log.v(TAG, "runQuery Constraint = " + constraint) ; 
       String selection = mDbHelper.KEY_NAME + " LIKE '%"+constraint+"%'"; 

       mDbHelper.open(); 
       Cursor c = mDbHelper.fetchFriendsWithSelection(
       (constraint != null ? constraint.toString() : null)); 
       return c; 
    } 
}); 




     setListAdapter(adapter); 

     Log.d(TAG, "setListAdapter worked") ; 


     listView.setItemsCanFocus(false); 
     listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 

     // listView.setOnItemClickListener(mListener); 

     Button btn; 
     btn = (Button)findViewById(R.id.buttondone); 

     mDbHelper.close(); 

    } 


    @Override 
    protected void onListItemClick(ListView parent, View v, int position, long id) { 

     String item = (String) getListAdapter().getItem(position); 
     Toast.makeText(this, item + " selected", Toast.LENGTH_LONG).show(); 

     //gets the Bookmark ID of selected position 
     Cursor cursor = (Cursor)parent.getItemAtPosition(position); 
     String bookmarkID = cursor.getString(0); 

     Log.d(TAG, "mListener -> bookmarkID = " + bookmarkID); 

     Log.d(TAG, "mListener -> position = " + position); 

//  boolean currentlyChecked = checkedStates.get(position); 
//  checkedStates.set(position, !currentlyChecked); 


     if (!selectedIds.contains(bookmarkID)) { 

      selectedIds.add(bookmarkID); 
      selectedLines.add(position); 

     } else { 

      selectedIds.remove(bookmarkID); 
      selectedLines.remove(position); 


      } 

    } 



    private TextWatcher filterTextWatcher = new TextWatcher() { 

     public void afterTextChanged(Editable s) { 

     } 

     public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

     } 

     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      Log.v(TAG, "onTextChanged called. s = " + s); 
      adapter.getFilter().filter(s); 
     } 
    }; 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     filterText.removeTextChangedListener(filterTextWatcher); 
    } 

Cursor Adaptor Tuỳ chỉnh của tôi:

public class FriendsSimpleCursorAdapter extends SimpleCursorAdapter implements Filterable { 

private static final String TAG = "FriendsSimpleCursorAdapter"; 
private final Context context ; 
private final String[] values ; 
private final int layout ; 
private final Cursor cursor ; 

static class ViewHolder { 
    public CheckedTextView checkedText ; 
} 

public FriendsSimpleCursorAdapter(Context context, int layout, Cursor c, 
     String[] from, int[] to) { 
    super(context, layout, c, from, to); 
    this.context = context ; 
    this.values = from ; 
    this.layout = layout ; 
    this.cursor = c ; 
    Log.d(TAG, "At the end of the constructor") ; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    Log.d(TAG, "At the start of rowView. position = " + position) ; 
    View rowView = convertView ; 
    if(rowView == null) { 
     Log.d(TAG, "rowView = null"); 
     try { 
     LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     rowView = inflater.inflate(layout, parent, false); 
     Log.d(TAG, "rowView inflated. rowView = " + rowView); 
     ViewHolder viewHolder = new ViewHolder() ; 
     viewHolder.checkedText = (CheckedTextView) rowView.findViewById(R.id.text1) ; 
     rowView.setTag(viewHolder); 
     } 
     catch (Exception e) { 
      Log.e(TAG, "exception = " + e); 
     } 
    } 

    ViewHolder holder = (ViewHolder) rowView.getTag(); 

    int nameCol = cursor.getColumnIndex(FriendsDbAdapter.KEY_NAME) ; 
    String name = cursor.getString(nameCol); 
    holder.checkedText.setText(name); 

    Log.d(TAG, "At the end of rowView"); 
    return rowView; 

} 

}

+0

Theo liên kết này, http://codereview.stackexchange.com/questions/1057/android-custom-cursoradapter-design, chúng tôi sẽ loại bỏ tốt hơn newView và bindView. – rohitmishra

Trả lời

1

Những gì tôi đã làm điều đó giải quyết nó:

cur = con trỏ. c = con trỏ bên trong simpleecursoradapter.

trong MainActivity tôi:

(members) 
static ArrayList<Boolean> checkedStates = new ArrayList<Boolean>(); 
static HashSet<String> selectedIds = new HashSet<String>(); 
static HashSet<Integer> selectedLines = new HashSet<Integer>(); 

trong onItemClickListener ListView:

if (!selectedIds.contains(bookmarkID)) { 

    selectedIds.add(bookmarkID); 
    selectedLines.add(position); 


} else { 

    selectedIds.remove(bookmarkID); 
    selectedLines.remove(position); 



if (selectedIds.isEmpty()) { 
    //clear everything 
     selectedIds.clear(); 
     checkedStates.clear();  
     selectedLines.clear(); 

     //refill checkedStates to avoid force close bug - out of bounds 
     if (cur.moveToFirst()) { 
      while (!cur.isAfterLast()) {  
       MainActivity.checkedStates.add(false); 

       cur.moveToNext(); 
      } 
     }      

} 

Trong SimpleCursorAdapter tôi đã thêm (cả trong getView):

// fill the checkedStates array with amount of bookmarks (prevent OutOfBounds Force close) 
     if (c.moveToFirst()) { 
      while (!c.isAfterLast()) { 
       MainActivity.checkedStates.add(false); 
       c.moveToNext(); 
      } 
     } 

và:

String bookmarkID = c.getString(0); 
     CheckedTextView markedItem = (CheckedTextView) row.findViewById(R.id.btitle); 
     if (MainActivity.selectedIds.contains(new String(bookmarkID))) { 
      markedItem.setChecked(true); 
      MainActivity.selectedLines.add(pos); 

     } else { 
      markedItem.setChecked(false); 
      MainActivity.selectedLines.remove(pos); 
     } 

Hope this helps ... bạn sẽ tất nhiên cần phải điều chỉnh nó cho nhu cầu của bạn.

EDIT:

Downloaded FB SDK, không thể có được thông qua việc đăng nhập FB. bạn có một lỗi mà bạn không nhận được access_token hợp lệ nếu ứng dụng FB được cài đặt trên thiết bị. Đã xóa ứng dụng FB và nhận một FC trong getFriends(). Giải quyết nó bằng cách gói phạm vi của nó với runOnUiThread(new Runnable...).

Lỗi bạn nhận được không liên quan đến lọc xấu, trạng thái hộp kiểm xấu ... Bạn nhận được thông báo vì bạn đang cố truy cập con trỏ trước khi truy vấn con trỏ (đã đóng). Có vẻ như bạn đang đóng con trỏ trước khi bộ điều hợp đang sử dụng nó. Xác minh bằng cách thêm:

mDbHelper = new FriendsDbAdapter(context); 

     mDbHelper.open() ; 
     cursor = mDbHelper.fetchAllFriends(); 

đến phạm vi getView trong SelectFriendsAdapter.

Sau khi bạn thêm, nó sẽ không FC và bạn có thể bắt đầu chăm sóc bộ lọc của bạn. Đảm bảo con trỏ không bị đóng và về cơ bản nếu bạn đang quản lý nó với startManagingCursor(), không cần đóng thủ công.

Hy vọng bạn có thể mang nó từ đây!

+0

Cảm ơn rất nhiều sự giúp đỡ của bạn. Tôi vẫn gặp phải sự cố trong setFilterQueryProvider. Sử dụng cùng một trình trợ giúp cơ sở dữ liệu như được sử dụng cho SimpleCursorAdapter là cho tôi một "Invalid Statement in fillWindow() error" Trong listactivity của tôi, tôi đã sử dụng một cá thể của mDbHelper là DatabaseHelper của tôi. Tôi thực hiện cuộc gọi đến c = mDbHelper.fetchAllFriends() theo sau là startManagingCursor() trong onCreate của listActivity của tôi. Tôi có nên khai báo một cá thể mDbHelper mới cho cuộc gọi trong runQuery() không? Tôi không thể tìm ra cách ưu tiên để giải quyết vấn đề này là gì. – rohitmishra

+0

@movingahead Tôi không chắc tôi hiểu cách giúp bạn và câu hỏi hiện tại của bạn liên quan đến những gì bạn đã mô tả trong bài đăng OP, NHƯNG, theo lỗi bạn nhận được, có vẻ như cách đúng là khởi tạo mDbHelper trong onCreate (new mDbHelper() hoặc bất kỳ thứ gì) và sau đó gọi hàm fetchFriends. Xem tại đây: 1. http://stackoverflow.com/questions/4195089/what-does-invalid-statement-in-fillwindow-in-android-cursor-mean 2. http://stackoverflow.com/questions/4258493/invalid-statement-in-fillwindow-in-android 3. http://stackoverflow.com/questions/9049542/invalid-statement-in-fillwindow –

+0

Tôi đã theo tất cả các liên kết mà bạn đã chỉ đến. Tôi đang gặp lỗi một hoặc một con trỏ khác. Dù sao, cảm ơn vì đã giúp. – rohitmishra

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