this is my QuestionHolder
:
private class QuestionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private JSONObject question;
private CheckBox checkBox;
private TextView question_txt;
public QuestionHolder(final LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.question_item, parent, false));
checkBox = (CheckBox) itemView.findViewById(R.id.question_checkbox);
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//try {
//Toast.makeText(getActivity(), "ID: " + question.get("_id"), Toast.LENGTH_SHORT).show();
//} catch (JSONException e) { }
// TODO: If this was checked then add the question's id to the answered list
}
});
question_txt = (TextView) itemView.findViewById(R.id.question);
itemView.setOnClickListener(this);
}
here I am binding the questiontxt
:
public void bind(JSONObject question) {
this.question = question;
try {
question_txt.setText(question.getString("_question"));
} catch (JSONException je) { }
}
@Override
public void onClick(View v) {
// TODO: If this was checked then add the question's id to the answered list
}
}
this is my Adapter which extend QuestionHolder
:
private class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {
private JSONArray questions;
public QuestionAdapter(JSONArray questions) {
this.questions = questions;
}
@Override
public QuestionHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
return new QuestionHolder(LayoutInflater.from(getActivity()), parent);
}
this is onBindViewHolder
:
@Override
public void onBindViewHolder(QuestionHolder holder, int position) {
try {
final JSONObject question = questions.getJSONObject(position);
holder.bind(question);
} catch (JSONException je) { }
}
@Override
public int getItemCount() {
return questions.length();
}
}
this is QuestionHolder
:
private class QuestionHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private JSONObject question;
private CheckBox checkBox;
private TextView question_txt;
public QuestionHolder(final LayoutInflater inflater, ViewGroup parent) {
super(inflater.inflate(R.layout.question_item, parent, false));
checkBox = (CheckBox) itemView.findViewById(R.id.question_checkbox);
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//try {
//Toast.makeText(getActivity(), "ID: " + question.get("_id"), Toast.LENGTH_SHORT).show();
//} catch (JSONException e) { }
// TODO: If this was checked then add the question's id to the answered list
}
});
question_txt = (TextView) itemView.findViewById(R.id.question);
itemView.setOnClickListener(this);
}
public void bind(JSONObject question) {
this.question = question;
try {
question_txt.setText(question.getString("_question"));
} catch (JSONException je) { }
}
@Override
public void onClick(View v) {
// TODO: If this was checked then add the question's id to the answered list
}
}
This is because your ViewHolder
is recycled when scrolling. So, you need to keep the state of the CheckBox for each item position. You can use SparseBooleanArray to handle this.
You can do something like this:
private class QuestionAdapter extends RecyclerView.Adapter<QuestionHolder> {
SparseBooleanArray checkedItems = new SparseBooleanArray();
...
@Override
public void onBindViewHolder(QuestionHolder holder, int position) {
try {
final JSONObject question = questions.getJSONObject(position);
// Remember to change access modifier of checkBox in your ViewHolder
// Get the state from checkedItems. If no previous value, it will return false.
holder.checkBox.setChecked(checkedItems.get(position));
// This is a sample. Do not use create listener here.
checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// save the check state
checkedItems.put(position, true);
}
holder.bind(question);
} catch (JSONException je) { }
}
...
}
RecyclerView removes (recycles) the unseen views from the layout on scrolling, this is the basic behavior of recyclerView in order to reduce memory use.
So when a view with a checkbox is "recycled", a checked checkbox gets unchecked and if it has a listener, the listener gets called.
You can remove the listener from the view when it is recycled. Just override the onViewRecycled method.
@Override
public void onViewRecycled(@NonNull MyViewHolder holder) {
if (holder.checkBox != null) {
holder.checkBox.setOnClickListener(null);
}
super.onViewRecycled(holder);
}
When the view is constructed again, while scrolling, your listener will also be added again.
After some research on this one of the complex issue
I did this like this for my currency convertor project:
Below are steps:
Coding:
Adapter and View Holder
class Adapter extends RecyclerView.Adapter<Adapter.VH> {
ArrayList<Currency> list, checkedCurrencies = new ArrayList<>();
CurrencySelectionChangelistener listener;
public Adapter(@NonNull ArrayList<Currency> list, CurrencySelectionChangelistener listener) {
this.list = list;
this.listener = listener;
}
@NonNull
@Override
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new VH(LayoutInflater.from(getContext()).inflate(R.layout.layout_list_of_all_items, parent, false));
}
@Override
public void onBindViewHolder(@NonNull VH holder, @SuppressLint("RecyclerView") int position) {
Currency currentCurrency = list.get(position);
holder.checkBox.setChecked(currentCurrency.isChecked());
holder.mDis.setText(currentCurrency.getDescription());
//ignore below line it's just for sorting the string to set On TextView and with another purpose
String name = currentCurrency.getName().toLowerCase().replace(" ", "");
holder.mName.setText(name.toUpperCase());
holder.mLogo.setImageResource(currentCurrency.getLogo(name));
holder.checkBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (holder.checkBox.isChecked()) {
list.get(position).setChecked(true);
checkedCurrencies.add(currentCurrency);
} else if (!holder.checkBox.isChecked()) {
list.get(position).setChecked(false);
checkedCurrencies.remove(currentCurrency);
}
//calling the interference's function
onSelection(checkedCurrencies);
}
});
}
@Override
public int getItemCount() {
return list.size();
}
class VH extends RecyclerView.ViewHolder {
TextView mName, mDis;
ImageView mLogo;
CheckBox checkBox;
public VH(@NonNull View itemView) {
super(itemView);
checkBox = itemView.findViewById(R.id.checkboxAllItems);
mLogo = itemView.findViewById(R.id.ImageViewAllItemLogo);
mName = itemView.findViewById(R.id.textViewAllItemCName);
mDis = itemView.findViewById(R.id.textViewAllItemCDis);
}
}
}
Interface
public interface CurrencySelectionChangelistener {
public void onSelection(ArrayList<Currency> currencies);}
Fragment in Which I'm using RecyclerView
public class AddMoreCurrencyFragment extends Fragment implements CurrencySelectionChangelistener {
FragmentAddNewCurrencyBinding binding;
ArrayList<Currency> currencies;
Adapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
binding = FragmentAddNewCurrencyBinding.inflate(inflater);
CurrencyContainerActivity.title.setVisibility(View.VISIBLE);
CurrencyContainerActivity.title.setText("Add Currency");
CurrencyContainerActivity.backBtn.setVisibility(View.VISIBLE);
currencies = new ArrayList<>();
for (Currency c : CurrencyContainerActivity.listOfCurrencies) {
currencies.add(new Currency(c.getName(), c.getDescription(), false));
}
adapter = new Adapter(currencies, this);
binding.recView.setAdapter(adapter);
binding.done.setOnClickListener(view -> {
});
return binding.getRoot();
}
@Override
public void onSelection(ArrayList<Currency> currencies) {
CurrencyContainerActivity.listToAdd.addAll(currencies);
Toast.makeText(getContext(), currencies.toString(), Toast.LENGTH_LONG).show();
adapter.notifyDataSetChanged();
}
}
xml layout for each item
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@color/white"
android:orientation="vertical"
android:weightSum="3">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="59dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="10dp"
android:weightSum="3">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.89"
app:cardCornerRadius="16dp">
<ImageView
android:id="@+id/ImageViewAllItemLogo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/flag" />
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/textViewAllItemCName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="19dp"
android:layout_weight=".75"
android:fontFamily="@font/poppins"
android:text="@string/pkr"
android:textAlignment="center"
android:textAllCaps="true"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/textViewAllItemCDis"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:layout_weight="0.47"
android:fontFamily="@font/poppins"
android:text="@string/pkr"
android:textAlignment="textStart"
android:textColor="@color/black"
android:textSize="13sp" />
<CheckBox
android:id="@+id/checkboxAllItems"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_weight="0.90"
android:background="@drawable/radio_selector"
android:button="@android:color/transparent" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#3F000000" />
</LinearLayout>
Model Class
public class Currency {
private String Name, Description;
private int logo;
boolean isChecked;
public Currency(String name, String description, boolean isChecked) {
Name = name;
Description = description;
this.isChecked = isChecked;
}
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
}
if anything i missed can for that. Thanks
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.