Пробую передать данные в Activity способом из этого ответа. В массиве myStr сейчас всегда оказывается последний элемент ListView.
Код моего адаптера:
public class MyCursorAdapter extends CursorAdapter {
private int layout; //нужен для создания объектов класса View
String[] myStr = new String[3];
//OnFavoriteListener callback;
public MyCursorAdapter(Context context, int layout, Cursor c, int flags) {
super(context, c, flags);
this.layout = layout;
}
public static class ViewHolder {
public TextView txtBukva;
public TextView txtSlovo;
public ImageButton btnIzbrannoe;
public void setBtnIzbrannoe(ImageButton btnIzbrannoe) {
this.btnIzbrannoe = btnIzbrannoe;
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(layout, parent, false);
return view;
}
@Override
public void bindView(View view, Context context, final Cursor cursor) {
final ViewHolder holder = new ViewHolder();
String bukva = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO)).substring(0, 1).toUpperCase();
final String slovo = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO));
final String izbrannoe = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));
int _ID = cursor.getInt(cursor.getColumnIndex(Contract.Entry._ID));
holder.txtBukva = (TextView) view.findViewById(R.id.txtBukva);
holder.txtSlovo = (TextView) view.findViewById(R.id.txtSlovo);
holder.btnIzbrannoe = (ImageButton) view.findViewById(R.id.btnIzbrannoe);
holder.txtBukva.setText(bukva);
holder.txtSlovo.setText(slovo);
holder.btnIzbrannoe.setFocusable(false);
if (izbrannoe.equals("1")) {
holder.btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
} else if (izbrannoe.equals("0")) {
holder.btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
}
myStr[0] = _ID + "";
myStr[1] = slovo;
myStr[2] = izbrannoe;
holder.btnIzbrannoe.setTag(myStr);
}
}
Как передать данные, соответствующие кликнутому айтему?
Вот такой код получился в MainActivity
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {
private AutoCompleteTextView txtSearch;
private Spinner spinner;
private ListView list;
private ImageButton btnClear;
DBHeler db;
private MySimpleCursorAdapter cursorAdapter;
final private static int LOADER_RUS = 0; //0 - потому что в spinner первое значение имеет id 0
final private static int LOADER_ENG = 1; //1 - потому что в spinner первое значение имеет id 1
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = new DBHeler(this);
try {
db.createDataBase();
db.openDataBase();
} catch (IOException ex) {
ex.printStackTrace();
}
spinner = (Spinner) findViewById(R.id.spinner);
txtSearch = (AutoCompleteTextView) findViewById(R.id.txtSearch);
list = (ListView) findViewById(R.id.list);
btnClear = (ImageButton) findViewById(R.id.btnClear);
ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(this, R.array.types, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
String[] from = new String[] {Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_PEREVOD, Contract.Entry.COLUMN_IZBRANNOE};
int[] to = new int[] {R.id.txtBukva, R.id.txtSlovo, R.id.txtPerevod, R.id.btnIzbrannoe};
cursorAdapter = new MySimpleCursorAdapter(this, R.layout.item, null, from, to, 0);
list.setAdapter(cursorAdapter);
// инициализируем оба загрузчика
getSupportLoaderManager().initLoader(LOADER_RUS, null, this);
getSupportLoaderManager().initLoader(LOADER_ENG, null, this);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
/*При выборе пункта в спинере обновление загрузчика происходит по нажатой позиции (а не по содержимому пункта списка) -
третий аргумент колбэка с именем loadID в данном коде передает позицию выбранного пункта.
Позиция может быть 0 или 1, ID наших загрузчиков так же 0 или 1 для русского и английского набора соответственно.*/
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int loadID, long l) {
getSupportLoaderManager().getLoader(loadID).forceLoad(); // обновляем данные в курсоре
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
@Override
protected void onResume() {
super.onResume();
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, SlovoActivity.class);
CharSequence strCharSequence = ((TextView)view.findViewById(R.id.txtSlovo)).getText();
String str = strCharSequence.toString().toLowerCase().trim();
String selectedItem = spinner.getSelectedItem().toString();
if (selectedItem.equals("С русского на английский")) {
intent.putExtra("slovo", str);
intent.putExtra("type", "RU");
startActivity(intent);
} else if (selectedItem.equals("С английского на русский")) {
intent.putExtra("slovo", str);
intent.putExtra("type", "EN");
startActivity(intent);
}
}
});
txtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
String[] from = new String[] {Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_SLOVO, Contract.Entry.COLUMN_PEREVOD, Contract.Entry.COLUMN_IZBRANNOE};
int[] to = new int[] {R.id.txtBukva, R.id.txtSlovo, R.id.txtPerevod, R.id.btnIzbrannoe};
cursorAdapter = new MySimpleCursorAdapter(MainActivity.this, R.layout.item, null, from, to, 0); list.setAdapter(cursorAdapter);
}
@Override
public void afterTextChanged(Editable editable) {
}
});
}
public void onFavoriteClick(View view) {
Slovo data = (Slovo)view.getTag();
long id = data.id;
String slovo = data.word;
String perevod = data.perevod;
String bukva = data.simbol;
boolean izbrannoe = data.favorite;
//System.out.println(id + " " + slovo + " " + perevod + " " + bukva + " " + izbrannoe);
if (izbrannoe == false) {
ContentValues values = new ContentValues();
values.put(Contract.Entry.COLUMN_IZBRANNOE, "1");
// Вставляем новый ряд в базу данных и запоминаем его идентификатор
long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
izbrannoe = true;
// Выводим сообщение в успешном случае или при ошибке
if (newRowId == -1) { // Если ID -1, значит произошла ошибка
Toast.makeText(this, "Ошибка", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Добавлено в избранное", Toast.LENGTH_SHORT).show();
getSupportLoaderManager().getLoader(LOADER_RUS).forceLoad();
}
} else if (izbrannoe == true) {
ContentValues values = new ContentValues();
values.put(Contract.Entry.COLUMN_IZBRANNOE, "0");
// Вставляем новый ряд в базу данных и запоминаем его идентификатор
long newRowId = db.database.update(Contract.Entry.TABLE_RUEN, values, Contract.Entry.COLUMN_SLOVO + "= ?", new String[]{slovo});
izbrannoe = true;
// Выводим сообщение в успешном случае или при ошибке
if (newRowId == -1) { // Если ID -1, значит произошла ошибка
Toast.makeText(this, "Ошибка", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Удалено из избранного", Toast.LENGTH_SHORT).show();
getSupportLoaderManager().getLoader(LOADER_RUS).forceLoad();
}
}
}
public void onClearBtnClick(View view) {
txtSearch.setText("");
btnClear.setVisibility(View.INVISIBLE);
}
protected void onDestroy() {
super.onDestroy();
db.close();
}
static class MyCursorLoader extends CursorLoader {
Cursor cursor;
DBHeler dbHeler;
final int loaderID;
public MyCursorLoader(Context context, DBHeler dbHeler, int id) {
super(context);
this.dbHeler = dbHeler;
loaderID = id;
}
@Override
protected Cursor onLoadInBackground() {
switch (loaderID) {
case LOADER_RUS:
cursor = dbHeler.getRuWords();
break;
case LOADER_ENG:
cursor = dbHeler.getEnWords();
break;
}
return cursor;
}
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new MyCursorLoader(this, db, id);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
cursorAdapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
cursorAdapter.swapCursor(null);
}
}
Поскольку у вас данные разного рода (число и строки), то разумнее использовать объект-модель для передачи данных. Кроме того, конкретно в вашем случае из-за ограничения готовой БД, которая хранит состояние избранного в виде строки, проведем полезное преобразование - логично это состояние представлять в виде boolean. Состояние true - в избранном, false - не в избранном, это сильно упростит логику обработки.
Создадим класс-модель (там где классы активити и проч.):
public class Data {
long id;
String word;
String simbol;
boolean favorite;
public Data(long id, String word, String simbol, String favorite) {
this.id = id;
this.word = word;
this.simbol = simbol;
this.favorite = (favorite.equals("1"))? true:false;
}
}
Теперь в адаптере заполняем эту модель и отправляем через тег (только необходимый для демонстрации код из адаптера):
public class MyCursorAdapter extends CursorAdapter {
public static class ViewHolder {
public TextView txtBukva;
public TextView txtSlovo;
public ImageButton btnIzbrannoe;
public ViewHolder(View view) {
txtBukva = (TextView) view.findViewById(R.id.txtBukva);
txtSlovo = (TextView) view.findViewById(R.id.txtSlovo);
btnIzbrannoe = (ImageButton) view.findViewById(R.id.btnIzbrannoe);
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(layout, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
return view;
}
@Override
public void bindView(View view, Context context, final Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
String bukva = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO)).substring(0, 1).toUpperCase();
final String slovo = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO));
final String izbrannoe = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));
long _ID = cursor.getLong(cursor.getColumnIndex(Contract.Entry._ID));
holder.txtBukva.setText(bukva);
holder.txtSlovo.setText(slovo);
holder.btnIzbrannoe.setFocusable(false);
if (izbrannoe.equals("1")) {
holder.btnIzbrannoe.setImageResource(R.drawable.icon_star_yellow);
} else {
holder.btnIzbrannoe.setImageResource(R.drawable.icon_star_outline_black);
}
// через конструктор устанавливаем значения для передачи в Activity
holder.btnIzbrannoe.setTag(new Data(_ID,slovo,bukva,izbrannoe);
}
}
Получаем в Activity:
public void onFavoriteClick(View view) {
Data data = (Data)view.getTag();
long id = data.id;
String slovo = data.word;
String bukva = data.simbol;
boolean izbrannoe = data.favorite;
}
Если данные планируется использовать за пределами кликера, то выносим локальные переменные в поля класса.
PS: Так же исправил использование паттерна ViewHolder. Назначение паттерна - кэшировать ссылки на объекты айтема (у вас эти ссылки получают каждый раз при биндинге в айтем и холдер в таком виде бесполезен). Дело в том, что получение ссылки на виджет из разметки методом findViewById() довольно ресурсоемкая операция, чтобы выполнять ее при создании каждого айтема, поэтому эти ссылки получают один раз при создании разметки, а затем хранят в холдере. Выше методы newView() и bindView() без сокращений кода.
PPS: значение ID из БД рекомендуется получать в long (а не int) так как это число может быть очень большим, рекомендую исправить (в примере внес исправления).
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости