2

В отдельном классе-адаптере определен ImageButton. Хочу из MainActivity обратиться к нему, чтобы реализовать добавление пунктов из Listview в избранное. Как обратиться мне?

Вот класс адаптера

public class MyCursorAdapter extends CursorAdapter {

    private int layout; //нужен для создания объектов класса View

    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) {
        ViewHolder holder = new ViewHolder();
        String bukva = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO)).substring(0, 1).toUpperCase();
        String slovo = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_SLOVO));
        String izbrannoe = cursor.getString(cursor.getColumnIndex(Contract.Entry.COLUMN_IZBRANNOE));

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

}
pavlofff
  • 36,765
user233150
  • 263
  • 1
  • 9
  • Я недавно здесь уже отвечал вопросы на основе очень похожего кода. Вы где-то учитесь сейчас? Где? – tse Jan 07 '17 at 21:24

3 Answers3

2

Первое - нужно определить интерфейс коллбэка, с помощью которого адаптер вернет в MainActivity информацию о нажатии на кнопку "избранное" в определенном пункте. Как-то так:

public interface OnFavoriteListener {
    void onFavoriteClicked(Integer id);
}

Второе - добавить в адаптер метод, которым будет передаваться объект-лиснер. Или передать его через конструктор.

public class MyCursorAdapter extends CursorAdapter {
    OnFavoriteListener callback;
    ....

    public void setOnFavoriteListener(OnFavoriteListener callback) {
        this.callback = callback;
    }
}

Третье. Нужно к каждому отображаемому элементу привязать его уникальный id. Что для вас является id, я не понимаю: есть в базе колонка с id, или это будет строчка из bukva или slovo. Выберите сами. Я бы это привязал к корневому view элемента. Соответственно, в bindView нужно сделать так:

public void bindView(View view, Context context, final Cursor cursor {
    ....

    Integer id = .....;
    view.setTag(id);
}

Четвертое. Нужен обработчик нажатий на кнопку, который восстановит id и передаст с помощью лиснера в MainActivity:

public View newView(Context context, Cursor cursor, ViewGroup parent) {
    ....
    view.findViewById(R.id.btnIzbrannoe).setOnClickListener(new OnClickListener() {
        void onClick(View v) {
            if (callback != null) { 
                Integer id = (Integer)v.getTag();
                callback.onFavoriteClicked(id);
            }
        });
    return view;
}

Пятое - в MainActivity создать лиснер нажатий на вашу кнопку, в нем записать изменение в БД и перегрузить адаптер.

Пишу "из головы", не проверяя, в коде могут быть опечатки, вникайте в суть.

tse
  • 3,716
  • 11
  • 25
  • Второе тоже не поняла как сделать. Я давно закончила, но java и тем более андроид-программирование мы не проходили даже близко. Поэтому сейчас тяжеловато. Что за переменная callback где ее объявить? (( – user233150 Jan 07 '17 at 21:30
  • Добавил колбэк. – tse Jan 07 '17 at 23:15
  • А из MainActivity обратиться к кнопке методом onFavoriteClicked() ?? onFavoriteClicked(Integer id); - тут id это идентификатор view? типа R.id.btnIzbrannoe ? – user233150 Jan 07 '17 at 23:22
  • Наоборот, это кнопка обратиться к MainActivity, когда по ней кликнут. Механизм по сути ничем не отличается от обычного click listener. – tse Jan 08 '17 at 11:46
  • Id - это записи, по которой вы сможете в БД изменить флаг "избранное". Чтобы понимать, на какой элемент клиенули. – tse Jan 08 '17 at 11:46
2

Если список находится в активити (а не фрагменте), то обработать клик на одном из View айтема списка можно очень просто. В xml-разметке айтема для нужной кнопки указываете атрибут onClick и указываете имя метода для обработки клика (здесь onFavoriteClick):

<Button
    android:id="@+id/btnIzbrannoe"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="onFavoriteClick"
    android:text="Favorite" />

В активити, которая отображает список, создаете метод с таким именем и следующей сигнатурой:

public void onFavoriteClick(View view) {

      // Действия при клике на кнопку btnIzbrannoe в айтеме

}

Необходимые дополнительные данные можно передать через setTag() для этой кнопки в адаптере и получить в активити из View, которую возвращает колбэк. Например, передать позицию курсора в адаптере:

Адаптер:

@Override
public void bindView(View view, Context context, final Cursor cursor) {
    ViewHolder holder = new ViewHolder();

    holder.btnIzbrannoe = (ImageButton) view.findViewById(R.id.btnIzbrannoe);
    holder.btnIzbrannoe.setTag(cursor.getPosition());
}

Активити:

public void onFavoriteClick(View view) {

      Integer position = (Integer)view.getTag();

}

Так можно передать любой объект, при необходимости нескольких данных можно использовать коллекции или составной объект-модель.

К сожалению в фрагментах такой простой способ не работает и требуется организовать свой интерфейс обратного вызова (колбэк)

pavlofff
  • 36,765
1

Вывод списка через отдельно созданный класс. Перед выводом добавлен OnClickListener для объекта класса:

        for (int i = 0; i < promoList.length(); ++i) {
        try {
            checksObj = promoList.getJSONObject(i);

            final PartFrameChecks partFrame = new PartFrameChecks(getApplicationContext());
            partFrame.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    getCheckDetails(partFrame.getChecks_num(), partFrame.getChecks_date());
                }
            });
            partFrame.setCheck_date(checksObj.getString(&quot;checks_date&quot;));
            partFrame.setSale_(&quot;Сумма покупки:&quot;, checksObj.getString(&quot;checks_mag&quot;), checksObj.getString(&quot;checks_num&quot;));
            partFrame.setSale_sum(checksObj.getString(&quot;checks_summ&quot;) + &quot; руб.&quot;);
            partFrame.setChecks_num(checksObj.getString(&quot;checks_num&quot;));

            liner.addView(partFrame);
        } catch (JSONException e) {
            Toast.makeText(this, &quot;Ошибка разборки объекта массива \n&quot; + ans, Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
    }

Сам класс выглядит, примерно, упрощенно так:

public class PartFrameChecks extends RelativeLayout {
private TextView check_date;
private TextView sale_;
private TextView sale_sum;
private TextView sale_mag;
private String checks_num;

private View view;
private Context contextLocalVar;

public PartFrameChecks(Context context) {
    super(context);
    initComponents(context);
}

private void initComponents(Context context) {

    LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    view = inflater.inflate(R.layout.custom_checks_layout, this);

    check_date  = view.findViewById(id.check_date);
    sale_       = view.findViewById(id.sale_text);
    sale_sum    = view.findViewById(id.sale_sum);
    sale_mag    = view.findViewById(id.sale_nom);
    checks_num  = &quot;&quot;;

    contextLocalVar = context;
};

public void setCheck_date(String text) {
    if(check_date != null) check_date.setText(text);
    else Toast.makeText(contextLocalVar, &quot;check_date is null. &quot;, Toast.LENGTH_LONG).show();
}

public void setSale_(String text, String mag, String p_checks_num) {
    if((sale_ != null) &amp;&amp; (sale_mag != null)) {
        checks_num = p_checks_num;
        sale_.setText(text);
        sale_mag.setText(mag + &quot;\n&quot; + checks_num);

    }
    else Toast.makeText(contextLocalVar, &quot;sale_ is null. &quot;, Toast.LENGTH_LONG).show();
}

public void setSale_sum(String text) {
    if(sale_sum!=null) sale_sum.setText(text);
    else Toast.makeText(contextLocalVar, &quot;sale_sum is null. &quot;, Toast.LENGTH_LONG).show();
}

public void setChecks_num(String text) {
    //checks_num = text;
}

public String getChecks_num() {
    return checks_num;
}

public String getChecks_date() {
    return check_date.getText().toString();
}

}

0xdb
  • 51,614