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+""

Надеюсь, что это сработает для вас.