Recyclerview чекбокс держать проверенную проблему? - PullRequest
0 голосов
/ 31 октября 2019

Решено: я использую специальный адаптер recyclerview с флажком, чтобы пользователь мог выбрать несколько отмеченных элементов.

В начале я столкнулся с дублированием выбора флажка при прокрутке вниз, поэтому я добавил массив позиций, чтобы сохранить выбор флажкаtrue или false. Теперь проблема выбора дубликатов флажков исчезла, но при прокрутке вниз выбранные флажки не выбраны. Мой adpaterviewviewler приведен ниже,

class IngredientsAdapter(var context: Context?,var activity: Activity, var ingredientList:ArrayList<String>, var imageID:Int):
        RecyclerView.Adapter<IngredientsAdapter.IngredientViewHolder>() {
    private var positionArray:ArrayList<Boolean> = ArrayList(ingredientList.size)
    private val selectedList=ArrayList<String>()
    init {
        for (i in ingredientList.indices) {
            positionArray.add(false)
        }
    }

    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): IngredientViewHolder {
        val layoutInflater = LayoutInflater.from(p0.context)
        return (IngredientsAdapter.IngredientViewHolder(layoutInflater.inflate(R.layout.ingredient_list_row,p0,false)))
    }

    override fun getItemCount(): Int {
       return ingredientList.size
    }
    override fun onBindViewHolder(p0: IngredientViewHolder, p1: Int) {


        p0.imageView.setImageResource(imageID)
        p0.textView.text = ingredientList[p1]
        //added for solution here
        p0.checkBox.setOnCheckedChangeListener(null)

        p0.checkBox.isChecked = positionArray[p1]
        val sharedPreferences= SharedPreferenceHelper(context, SystemConstants.SHARED_PREFS_CHECKDATA)
        val checked=sharedPreferences.getPrefsBooleanValue(ingredientList[p1])
        p0.checkBox.isChecked = checked
        p0.checkBox.setOnCheckedChangeListener(CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
            if(isChecked){
                positionArray[p1] = true
                selectedList.add(ingredientList[p1])
                ingredientList.get(p1)
                sharedPreferences.addPrefsBooleanVal(ingredientList[p1],true)
                Log.d("debug","selecteditem==>$selectedList")
            }else{
                positionArray[p1] = false
                selectedList.remove(ingredientList[p1])
                sharedPreferences.addPrefsBooleanVal(ingredientList[p1],false)
                Log.d("debug","selecteditem==>$selectedList")
            }
        })
    }

    class IngredientViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var textView= itemView.txt_row!!
        var imageView= itemView.image_view!!
        var checkBox= itemView.chk_row!!
    }
}

Любое предложение приветствуется.

Ответы [ 3 ]

0 голосов
/ 31 октября 2019
Когда вы звоните setOnCheckedChangeListener, у флажка есть прослушиватель, а при повторной прокрутке просмотр повторного просмотра будет мультиплексным. и вы применяете p0.checkBox.isChecked = positionArray[p1], на самом деле вы меняете последнее положение. Например, вы устанавливаете первый флажок, arrray[0] имеет значение true, затем прокручиваете представление, следующий элемент, возможно, четвертый или пятый будет иметь такой же флажок.

Затем вы снова вызываете p0.checkBox.isChecked = positionArray[p1], но слушателю принадлежит первый элемент. тогда слушатель изменит array[0]. Таким образом, вы должны позвонить p0.checkBox.setOnCheckedChangeListener до p0.checkBox.isChecked = positionArray[p1]

0 голосов
/ 01 ноября 2019

То, что @Bek предложил, является правильным решением. Вам нужно будет использовать OnClickListener. Также то, что вы прокомментировали, тоже не так, просто то, что вы использовали (ListView), есть или было!

Позвольте мне разобрать это для вас:

  1. ListView : Старая версия RecyclerView.

    Интересно, почему разработчик создал еще один избыточный компонент? В основном проблема с памятью! ListView создает столько ItemViews, сколько ему требуется, тогда как RecyclerView просто перерабатывает itemView.
    Например, если для списка из 100 элементов, если мы используем ListView, он первоначально создаст столько ItemViews, сколько может отобразить телефон. Затем, когда мы прокручиваем вниз, он продолжает создавать больше видов до 100-го элемента (100 элементов в памяти). Но RecyclerView делает это более эффективно, он создает столько представлений, которые он может показать + 1 (следующий вид в списке), затем он продолжает их перерабатывать, поэтому у нас всегда есть только столько представлений на экране +1, а не 100, когда мы достигаем нижней части списка. ,Для более подробной информации прочитайте это и это .

  2. OnCheckChangeListener : Другой источник проблем!

    Этот слушатель вызывается всякий раз, когда проверяются изменения для флажка, Всякий раз ! Так что, если я обновлю флажок, этот слушатель (теоретически) будет вызван! Куда я иду с этим? Да, когда используется вместе с RecyclerView, это приведет к хаосу в коде. В тот момент, когда recyclerView уничтожает или повторно использует ItemView, флажок сбрасывается, что запускает слушателя и заставляет ваш SharedPref переписать проверку! Я проверил это, добавив журналы внутри слушателя и увидел, что он запускается для большинства внешних видов, когда он перерабатывается.

Это только мои выводы, возможно, есть какой-то способ или исправить это, ноя бы также предложил использовать OnClickListener и написать слушатель для изменения модели в основном классе, а не sharedPref в адаптере.

О! Вы можете использовать ViewHolder.SetIsRecyclable (false), это остановит RecyclerView от повторной обработки представлений и создаст столько представлений, сколько элементов в списке. Но я бы не советовал этого делать, так как пользовательский интерфейс, а также UX будут скомпрометированы, поскольку при прокрутке вы можете столкнуться с некоторой задержкой (проблема с памятью)!

Long Story Краткое использование OnClickListener с RecyclerView!

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

Вы можете использовать класс Model для отслеживания каждого флажка элемента recyclerView. Используйте setTag и getTag используется для отслеживания состояния флажка.

Make Model

public class Model {

private boolean isSelected;
private String animal;

public String getAnimal() {
    return animal;
}

public void setAnimal(String animal) {
    this.animal = animal;
}

public boolean getSelected() {
    return isSelected;
}

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

create integer.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="btnplusview">1</integer>
<integer name="btnpluspos">2</integer>
</resources>

Наконец-то адаптер выглядит так:

 import android.content.Context;
 import android.support.v7.widget.RecyclerView;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.CheckBox;
 import android.widget.TextView;
 import android.widget.Toast;
 import java.util.ArrayList;


public class CustomAdapter extends 
RecyclerView.Adapter<CustomAdapter.MyViewHolder> {

private LayoutInflater inflater;
public static ArrayList<Model> imageModelArrayList;
private Context ctx;

public CustomAdapter(Context ctx, ArrayList<Model> imageModelArrayList) {
inflater = LayoutInflater.from(ctx);
this.imageModelArrayList = imageModelArrayList;
this.ctx = ctx;
}

@Override
public CustomAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent, int 
viewType) {

View view = inflater.inflate(R.layout.rv_item, parent, false);
MyViewHolder holder = new MyViewHolder(view);

return holder;
}

@Override
public void onBindViewHolder(final CustomAdapter.MyViewHolder holder, int 
position) {
holder.checkBox.setText("Checkbox " + position);
holder.checkBox.setChecked(imageModelArrayList.get(position).getSelected());
holder.tvAnimal.setText(imageModelArrayList.get(position).getAnimal());

// holder.checkBox.setTag(R.integer.btnplusview, convertView);
holder.checkBox.setTag(position);
holder.checkBox.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        Integer pos = (Integer) holder.checkBox.getTag();
        Toast.makeText(ctx, imageModelArrayList.get(pos).getAnimal() + " 
clicked!", Toast.LENGTH_SHORT).show();

        if (imageModelArrayList.get(pos).getSelected()) {
            imageModelArrayList.get(pos).setSelected(false);
        } else {
            imageModelArrayList.get(pos).setSelected(true);
        }
  }
});


}

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

class MyViewHolder extends RecyclerView.ViewHolder {

protected CheckBox checkBox;
private TextView tvAnimal;

public MyViewHolder(View itemView) {
    super(itemView);

    checkBox = (CheckBox) itemView.findViewById(R.id.cb);
    tvAnimal = (TextView) itemView.findViewById(R.id.animal);
    }

}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...