Questo problema è discusso in questa domanda Android: Wrong item checked when filtering listview. Per riassumere il problema, quando si utilizza un listview con un CursorAdapter e un filtro, gli elementi selezionati in un elenco filtrato perdono la loro selezione dopo che il filtro è stato rimosso e, invece, gli elementi in quella posizione nell'elenco non filtrato vengono selezionati.Implementazione di un listview con selezione multipla con filtro utilizzando un adattatore per cursori
Utilizzando l'esempio di codice nella domanda collegata sopra, dove dovremmo inserire il codice per contrassegnare le caselle di controllo. Credo che dovrebbe essere nel metodo getView() di CustomCursorAdapter, ma non sono sicuro. Inoltre, come possiamo accedere a HashSet tenendo tutti gli ID selezionati nella classe dell'adattatore personalizzato, poiché verrà inizializzato e modificato nell'attività principale che contiene l'elenco.
La mia attività di attuazione del 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);
}
mio adattatore cursore personalizzato:
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;
}
}
In base a questo collegamento, http://codereview.stackexchange.com/questions/1057/android-custom-cursoradapter-design, è preferibile ignorare newView e bindView. – rohitmishra