Пробую передать данные в 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
) так как это число может быть очень большим, рекомендую исправить (в примере внес исправления).
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Как в TextView записать химическую формулу с верхними и нижними символами?
Для реализации табов использую :target, но при загрузке страницы нужно чтобы первый блок был видимБлоки будут выводится динамически