2012-02-22 21 views
8

在此問題中討論此問題Android: Wrong item checked when filtering listview。爲了總結這個問題,當使用具有CursorAdapter和過濾器的列表視圖時,在過濾器被移除之後,在過濾列表上選擇的項目將失去它們的選擇,相反,未過濾列表中該位置上的項目將被選中。使用光標適配器實現帶有多個使用篩選器的選擇列表視圖

使用上面的鏈接的問題,我們應該在哪裏把代碼標記的複選框的代碼示例。我相信它應該在CustomCursorAdapter的getView()方法中,但我不確定。另外,我們如何訪問HashSet來保存自定義適配器類中的所有selectedIds,因爲它將在保存列表的主活動中進行初始化和修改。

我的活動實現的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); 
    } 

我的自定義光標適配器:

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

根據這個鏈接,http://codereview.stackexchange.com/questions/1057/android-custom-cursoradapter-design我們最好重寫newView和bindView。 – rohitmishra 2012-02-22 19:11:42

回答

1

我所做的是解決它:

CUR =光標。 c = simplecursoradapter內部遊標。

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

在ListView onItemClickListener

在我的MainActivity

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

} 

在SimpleCursorAdapter我加了(無論是在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(); 
      } 
     } 

和:

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

希望這有助於...你當然需要將其調整到您的需要。

編輯:

下載FB SDK,無法獲得通過FB登錄。如果FB應用程序安裝在設備上,則會出現一個錯誤,即您沒有獲得有效的access_token。取消了FB應用程序並獲得了getFriends()的FC。通過將其範圍與runOnUiThread(new Runnable...)包裝解決。

你無關壞過濾的錯誤,錯誤的複選框的狀態...你得到它,因爲你想查詢之前訪問光標(已關閉)。 看起來好像你在適配器使用它之前關閉了光標。通過添加:

mDbHelper = new FriendsDbAdapter(context); 

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

到SelectFriendsAdapter中的getView範圍。

後添加此,它不會FC,你可以開始把你的過濾器的保養。 確保光標未關閉,基本上如果您使用startManagingCursor()進行管理,則不需要手動關閉它。

希望你能從這裏拿下它!

+0

非常感謝您的幫助。我仍然在setFilterQueryProvider中遇到麻煩。使用與用於SimpleCursorAdapter的數據庫幫助程序相同的數據庫幫助程序給我一個「fillWindow()中的無效語句錯誤」 在我的列表活動中,我使用了一個mDbHelper實例,它是我的DatabaseHelper。我調用了c = mDbHelper.fetchAllFriends(),後面跟着我的listActivity的onCreate中的startManagingCursor()。 我應該爲runQuery()中的調用聲明一個mDbHelper的新實例嗎?我無法找到處理這個問題的首選方法。 – rohitmishra 2012-02-24 19:20:16

+0

@movingahead我不知道我是否理解如何爲您提供幫助,以及您當前的問題如何與您在OP中描述的內容相關,但是,在收到錯誤之後,似乎正確的方法是實例化mDbHelper onCreate(新的mDbHelper()或其他),然後調用fetchFriends。 請參閱: 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 – 2012-02-24 20:19:03

+0

我遵循了所有指向的鏈接。我得到一個或另一個遊標錯誤。無論如何,感謝您的幫助。 – rohitmishra 2012-02-24 21:54:48

相關問題