Android-смежные кнопки в режиме списка автоматически
Я работаю над модулем, который заполняет корзину. Я использовал ListView
и расширенный BaseAdapter
для заполнения элементов корзины.
С каждым элементом в ListView
я вложил две кнопки (вкл. И dec) для увеличения и уменьшения количества элементов в корзине.
ListView
правильно обновляется, но кнопка увеличения/уменьшения при быстром нажатии/нажатии показывает резкое поведение.
Всякий раз, когда я быстро нажимаю любую кнопку inc или dec, автоматически включается соответствующая кнопка inc или dec элемента рядом с текущим элементом в ListView
(вместе с текущим пунктом btn).
Другими словами, всякий раз, когда я быстро нажимаю inc btn i-го элемента в ListView
, автоматически включается inc btn я + 1-го элемента в ListView
(вместе с inc btn i-го элемента).
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_cart, parent, false);
holder = new ViewHolder();
holder.baseItem = (TextView) convertView.findViewById(R.id.qnt_tv);
holder.qntInc = (TextView) convertView.findViewById(R.id.inc_btn);
holder.qntDec = (TextView) convertView.findViewById(R.id.dec_btn);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
final CartModel cm = mCart.get(position);
holder.baseItem.setText(cm.getmTitle());
holder.qntSel.setText(String.valueOf(cm.getmQnt()));
holder.qntInc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (qntSpinnerCb != null)
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), INCREASE_QNT);
}
});
holder.qntDec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (qntSpinnerCb != null) {
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), DECREASE_QNT);
}
}
});
return convertView;
}
Интерфейс для обратного вызова
public interface CartQntSpinnerListenerCallBack {
void changeQuantityOfSelectedItemInCart(String iId, char changeType);
}
Пробовал отлаживать, не в состоянии понять это странное поведение.
Ответы
Ответ 1
Вы не выбираете правильный CartModel
внутри onClick
, если хотите получить правильный объект внутри onClick
, тогда вам нужно пометить позицию кнопкой
holder.qntInc.setTag(position);
в onClick:
@Override
public void onClick(View view) {
if (qntSpinnerCb != null) {
CartModel cm= mCart.get((Integer)view.getTag);
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), INCREASE_QNT);
}
}
Следуйте тому же для qntDec
.
Ответ 2
Если вы хотите сохранить свою текущую реализацию, сделайте это.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_cart, parent, false);
}
ViewHolder holder = new ViewHolder();
holder.baseItem = (TextView) convertView.findViewById(R.id.qnt_tv);
holder.qntInc = (TextView) convertView.findViewById(R.id.inc_btn);
holder.qntDec = (TextView) convertView.findViewById(R.id.dec_btn);
...
Однако, не видя остальной части вашего кода, я думаю, вы можете пересмотреть, как вы реализуете BaseAdapter. Традиционно они используются вместе со списком, чтобы перерабатывать представления для повышения эффективности. Это означает, что когда список прокручивает представление вне кадра, вместо перерисовки представления - if (convertView == null) - он повторно использует его. Я думаю, что вы испытываете то, что вы помещаете прослушиватель кликов для двух разных объектов на одной и той же кнопке.
То, что я бы рекомендовал сделать, это нечто большее:
@Override
public int getCount() {
return objects.size();
}
@Override
public CartModel getItem(int position) {
// mCart sounds like a single item but is a list? I advise you to rename
return objects.get(position);
}
@Override
public long getItemId(int position) {
// Implement with id. Copied the id call from your code..
return getItem(position).getmIid();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_cart, parent, false);
}
CartModel cm = getItem(position);
TextView baseItem = (TextView) convertView.findViewById(R.id.qnt_tv);
baseItem.setText(cm.getmTitle());
// Organize like items together for readability
TextView qntInc = (TextView) convertView.findViewById(R.id.inc_btn);
qntInc.setTag(mCartKey, cm);
qntInc.setOnClickListener(this);
// readability
TextView qntDec = (TextView) convertView.findViewById(R.id.dec_btn);
qntDec.setTag(mCartKey, cm);
qntDec.setOnClickListener(this);
// Defined in convert view?
qntSel.setText(String.valueOf(cm.getmQnt()));
return convertView;
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.R.id.inc_btn:
CartModel cm = (CartModel)v.getTag(mCartKey);
// What is this?
if (qntSpinnerCb != null)
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), INCREASE_QNT);
break;
case R.id.dec_btn:
CartModel cm = (CartModel)v.getTag(mCartKey);
if (qntSpinnerCb != null) {
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), DECREASE_QNT);
}
break;
}
}
ПРИМЕЧАНИЕ. Класс BaseAdapter должен реализовать OnClickListener
Ответ 3
сохраните позицию вашего представления в viewholder
и используйте его везде, где в setonclicklistner
от viewholder
в этой позиции вы не увидите никакого абсурдного поведения, которое будет работать так, как вы хотите
static class ViewHolder {
TextView baseItem, qntInc, qntDec;
....../* your code goes here */
int position
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_cart, parent, false);
holder = new ViewHolder();
holder.baseItem = (TextView) convertView.findViewById(R.id.qnt_tv);
holder.qntInc = (TextView) convertView.findViewById(R.id.inc_btn);
holder.qntDec = (TextView) convertView.findViewById(R.id.dec_btn);
holder.position=position
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
holder.position=position;
}
CartModel cm = mCart.get(holder.position);
holder.baseItem.setText(cm.getmTitle());
holder.qntSel.setText(String.valueOf(cm.getmQnt()));
holder.qntInc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CartModel cm = mCart.get(holder.position);
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), INCREASE_QNT);
}
});
holder.qntDec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
CartModel cm = mCart.get(holder.position);
qntSpinnerCb.changeQuantityOfSelectedItemInCart(cm.getmIid(), DECREASE_QNT);
}
});
return convertView;
}
также проверьте значение INCREMENT_QNT
и DECREACE_QNT
Ответ 4
В коде есть проблема.
if (convertView == null) {
convertView = mInflater.inflate(R.layout.list_item_cart, parent, false);
holder = new ViewHolder();
holder.baseItem = (TextView) convertView.findViewById(R.id.qnt_tv);
holder.qntInc = (TextView) convertView.findViewById(R.id.inc_btn);
holder.qntDec = (TextView) convertView.findViewById(R.id.dec_btn);
// This should be added in the code
holder.qntSel = (TextView) convertView.findViewById(R.id.sec_txt);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Ответ 5
У вашего метода getter getmIid()
в CartModel
есть проблема, я подозреваю. Этот метод возвращает неверный индекс, поэтому ваша следующая/предыдущая кнопка обновляет
Я предлагаю использовать position
integer в вашем первом обратном вызове changeQuantityOfSelectedItemInCart()
. Поскольку позиция всегда будет правильно соответствовать getView()
обратному вызову
РЕШЕНИЕ:
holder.qntInc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (qntSpinnerCb != null)
qntSpinnerCb.changeQuantityOfSelectedItemInCart(position+"", INCREASE_QNT);
}
});
holder.qntDec.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (qntSpinnerCb != null)
qntSpinnerCb.changeQuantityOfSelectedItemInCart(position+"", DECREASE_QNT);
}
});
Тип position
- int
, и ваш обратный вызов нуждается в String
, поэтому мы должны использовать position+""
Надеюсь, что это сработает для вас.