Как заставить CheckBox в recyclerView работать корректно? - PullRequest
0 голосов
/ 03 октября 2019

У меня есть recyclerView с кучей предметов, которые имеют флажок, чтобы отметить наличие. После того, как флажок установлен, элемент должен появиться в утилизаторе, и это делается путем обновления базы данных. Этот формат работает для некоторых элементов, особенно тех, которые находятся в конце рециркулятора, и не работает для других. Как я могу это исправить?

 public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemHolder> {
private TextView viewName, viewPrice, viewStock;
private CheckBox viewAvailability;

private Context context;
private List<Item> listItems;

private DBHelper db;
@NonNull
@Override
public ItemAdapter.ItemHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

    View view = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
    return new ItemAdapter.ItemHolder(view);
}

@Override
public void onBindViewHolder(@NonNull ItemAdapter.ItemHolder holder, int position) {
    Item item = listItems.get(position);
    holder.setDetails(item);

}

@Override
public int getItemCount() {
    return listItems.size();
}


public class ItemHolder extends RecyclerView.ViewHolder {
    public ItemHolder(final View itemView) {
        super(itemView);
        viewName = itemView.findViewById(R.id.viewName);
        viewPrice = itemView.findViewById(R.id.viewPrice);
        viewStock = itemView.findViewById(R.id.viewStock);
        viewAvailability = itemView.findViewById(R.id.viewAvailability);
    }

    public void setDetails(final Item item) {
        db = new DBHelper(context);
        viewName.setText(item.getName());
        viewPrice.setText(item.getPrice());
        viewStock.setText(String.valueOf(item.getStock()));
        int as = item.getAvailabilityStatus();

        if (as == 1) {
            viewAvailability.setChecked(true);
        } else {
        }

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Toast.makeText(context, String.valueOf(item.getId()), Toast.LENGTH_SHORT).show();
                Bundle dataBundle = new Bundle();
                dataBundle.putInt("id",item.getId());
                Intent intent = new Intent(context,NewItemActivity.class);
                intent.putExtras(dataBundle);
                context.startActivity(intent);
            }
        });

        viewAvailability.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if (viewAvailability.isChecked()){
                    //Toast.makeText(context, item.getId() + "is checked", Toast.LENGTH_SHORT).show();
                    //db.updateItem(new Item(item.getName(),item.getPrice(),1,0));
                   // db.updateItem(item.getId(),item.getName(),item.getPrice(),1,0);
                    changeAvailabilty(item.getId(),item.getName(),item.getPrice(),1,1,0);
                } else {
                   // db.updateItem(new Item(item.getName(),item.getPrice(),0,0));
                   // db.updateItem(item.getId(),item.getName(),item.getPrice(),0,0);
                    changeAvailabilty(item.getId(),item.getName(),item.getPrice(),1,0,0);
                }
            }
        });
    }
}

public ItemAdapter(Context context, List<Item> objects) {
    this.context = context;
    this.listItems = objects;
}

public void changeAvailabilty(int id, String name, String price, int stock, int av, int st) {
    if (av == 1){
        db.updateItem(id,name,price, stock,av,st);
        Toast.makeText(context, "is checked", Toast.LENGTH_SHORT).show();
    } else {
        db.updateItem(id,name,price, stock,av,st);
        Toast.makeText(context, "is not checked", 

Toast.LENGTH_SHORT).show();
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 03 октября 2019

Внутри setOnCheckedChangeListener из viewAvailability установите AvailabilityStatus на 1, когда пользователь проверил chckbox, в противном случае установите его 0. как показано ниже.

viewAvailability.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if (viewAvailability.isChecked()){
                    //Toast.makeText(context, item.getId() + "is checked", Toast.LENGTH_SHORT).show();
                    //db.updateItem(new Item(item.getName(),item.getPrice(),1,0));
                   // db.updateItem(item.getId(),item.getName(),item.getPrice(),1,0);
                    changeAvailabilty(item.getId(),item.getName(),item.getPrice(),1,1,0);

                   // here you have to set Availability Status is 1
                   item.setAvailabilityStatus(1)
                } else {
                   // db.updateItem(new Item(item.getName(),item.getPrice(),0,0));
                   // db.updateItem(item.getId(),item.getName(),item.getPrice(),0,0);
                    changeAvailabilty(item.getId(),item.getName(),item.getPrice(),1,0,0);

                   // here you have to set Availability Status is 0
                   item.setAvailabilityStatus(0)
                }
            }
        });
    }

ОБНОВЛЕНИЕ

В свой класс модели Item добавьте дополнительное свойство с именем isSelected с getter и setter like

public class Item{
    // your other properties

    private boolean isSelected;

    public boolean getSelected() {
        return isSelected;
    }

    public void setSelected(boolean selected) {
        isSelected = selected;
    }
}

И в вашем адаптере вы должны установить isSelected равным true, если пользователь проверил chekcbox, иначе установите его как false внутри вашего setDetails(). как следующие.

public void setDetails(final Item item) {
        db = new DBHelper(context);
        viewName.setText(item.getName());
        viewPrice.setText(item.getPrice());
        viewStock.setText(String.valueOf(item.getStock()));
        int as = item.getAvailabilityStatus();

        // Here you should check if it is already checked or not
        if (item.getSelected) {
            viewAvailability.setChecked(true);
        } 

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //Toast.makeText(context, String.valueOf(item.getId()), Toast.LENGTH_SHORT).show();
                Bundle dataBundle = new Bundle();
                dataBundle.putInt("id",item.getId());
                Intent intent = new Intent(context,NewItemActivity.class);
                intent.putExtras(dataBundle);
                context.startActivity(intent);
            }
        });

        viewAvailability.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
                if (viewAvailability.isChecked()){
                    //Toast.makeText(context, item.getId() + "is checked", Toast.LENGTH_SHORT).show();
                    //db.updateItem(new Item(item.getName(),item.getPrice(),1,0));
                   // db.updateItem(item.getId(),item.getName(),item.getPrice(),1,0);
                    changeAvailabilty(item.getId(),item.getName(),item.getPrice(),1,1,0);

                   // here you have to set selected true
                   item.setSelected(true)
                } else {
                   // db.updateItem(new Item(item.getName(),item.getPrice(),0,0));
                   // db.updateItem(item.getId(),item.getName(),item.getPrice(),0,0);
                    changeAvailabilty(item.getId(),item.getName(),item.getPrice(),1,0,0);

                   // here you have to set selected false
                   item.setSelected(false)
                }
            }
        });
    }

Надеюсь, это поможет вам. Счастливое кодирование

0 голосов
/ 03 октября 2019

Переопределите эти методы в вашем ItemAdapter

@Override
public int getItemViewType(int position) {
    return position; // return position
}

@Override
public long getItemId(int position) {
    return position; // return position
}

Эти методы помогают recyclerView уникально идентифицировать элементы, что устранит проблему с вашим флажком.

0 голосов
/ 03 октября 2019

У меня есть обходной путь с этим.

Проблема с чекбоксом и представлением переработчика в сочетании с тем, что при прокрутке просмотра переработчика держатель уничтожается, равно как и состояние владельцев, поэтому если вы хотите сохранить состояние просмотраВы должны сохранить его либо в видоискателе, либо в данных, которые отображает просмотрщик.

, как если бы вы отображали элемент

private List<Item> listItems;

в классе элементов списка, включите логическое значение ischecked и по умолчанию установите егоfalse.

всякий раз, когда вы устанавливаете флажок, пишите

listitems.checkboxstate=false;

, а когда вы отображаете состояние флажка, делайте его истинным

listitems.checkboxstate=true;

, но перед этим вы должныубедитесь, что флажок был предварительно установлен или нет

if(listitems.checkboxstate){checkbox.setchecked(true)}
else{checkbox.setchacked(false)}
...