Checkbox refreshing in false when I use notifyDataSetChanged(); - java

My problem is the one wrote on the title, I have a recyclerview with checkboxes and radiobuttons before I started to use the notifyDataSetChanged() (because I need to update the recyclerview) the checkboxes and radiobuttons were been checked, but now the checks don't work. (I think that it work but it becomes false instantly)
I am sure of this because if I comment the line of notifyDataSetChanged() then it still working as well.
Do you guys know how to fix it?
Java for the adapter Class:
public class OptionModesAdapter extends RecyclerView.Adapter<OptionModesAdapter.ViewHolder> {
private int fatherMode;
private int fatherId;
private Context context;
private AsyncAdapters asyncAdapters;
private ArrayList<Modes> modes;
private ArrayList<Modes> selected;
private ArrayList<IUrbanRadioButton> radiosSelected;
OptionModesAdapter(ArrayList<Modes> modes, Context context, int fatherMode, AsyncAdapters asyncAdapters) {
this.modes = modes;
this.context = context;
this.fatherMode = fatherMode;
this.selected = new ArrayList<>();
this.asyncAdapters = asyncAdapters;
this.radiosSelected = new ArrayList<>();
}
class ViewHolder extends RecyclerView.ViewHolder {
private CheckBox cbOptionMode;
private IUrbanRadioButton rbOptionMode;
ViewHolder(View itemView) {
super(itemView);
cbOptionMode = itemView.findViewById(R.id.cb_option_mode);
rbOptionMode = itemView.findViewById(R.id.rb_option_mode);
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View myView = LayoutInflater.from(parent.getContext()).inflate(R.layout.option_modes, parent, false);
return new OptionModesAdapter.ViewHolder(myView);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
switch (fatherMode) {
case 0:
holder.rbOptionMode.setVisibility(View.VISIBLE);
holder.cbOptionMode.setVisibility(View.GONE);
holder.rbOptionMode.setText(modes.get(position).getTranslationName(context));
holder.rbOptionMode.setParentName(String.valueOf(modes.get(position).getIdFather()));
onClickRadioButton(holder.rbOptionMode, position);
break;
case 1:
holder.cbOptionMode.setVisibility(View.VISIBLE);
holder.rbOptionMode.setVisibility(View.GONE);
holder.cbOptionMode.setText(modes.get(position).getTranslationName(context));
onClickCheckBox(holder.cbOptionMode, position);
break;
default:
Log.e(CustomConstants.EXCEPTION, "OptionModesAdapter: ln 72. Esto no es un modo admitido");
break;
}
}
private void onClickCheckBox(final CheckBox checkBox, final int position) {
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (selectedContainsCB(checkBox)) {
removeOldCb(checkBox);
} else {
addNewCb(checkBox);
}
fatherId = modes.get(position).getIdFather();
asyncAdapters.onInnerClicked(selected, false, fatherId);
}
});
}
private boolean selectedContainsCB(CheckBox checkBox) {
Modes newMode = findModeByCheckBox(checkBox);
return selected.contains(newMode);
}
private Modes findModeByCheckBox(CheckBox checkBox) {
Modes modeToReturn = new Modes();
for (Modes currentMode : modes) {
if (currentMode.getTranslationName(context).equals(checkBox.getText().toString())) {
modeToReturn = currentMode;
break;
}
}
return modeToReturn;
}
private void removeOldCb(CheckBox checkBox) {
Modes modeToRemove = findModeByCheckBox(checkBox);
checkBox.setChecked(false);
selected.remove(modeToRemove);
}
private void addNewCb(CheckBox checkBox) {
Modes modeToAdd = findModeByCheckBox(checkBox);
checkBox.setChecked(true);
selected.add(modeToAdd);
}
private void onClickRadioButton(final IUrbanRadioButton iUrbanRadioButton, final int position) {
iUrbanRadioButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
settingFalseAllRadios();
deletingAllModesRadios();
addNewRb(iUrbanRadioButton);
radiosSelected.add(iUrbanRadioButton);
iUrbanRadioButton.setChecked(true);
fatherId = modes.get(position).getIdFather();
asyncAdapters.onInnerClicked(selected, true, fatherId);
}
});
}
private void settingFalseAllRadios() {
for (IUrbanRadioButton iUrbanRadioButton : radiosSelected) {
iUrbanRadioButton.setChecked(false);
}
radiosSelected.clear();
}
private void deletingAllModesRadios() {
selected.clear();
}
private Modes findModeByRadioButton(IUrbanRadioButton iUrbanRadioButton) {
Modes modeToReturn = new Modes();
for (Modes currentMode : modes) {
if (currentMode.getTranslationName(context).equals(iUrbanRadioButton.getText().toString())) {
modeToReturn = currentMode;
break;
}
}
return modeToReturn;
}
private void addNewRb(IUrbanRadioButton iUrbanRadioButton) {
Modes modeToAdd = findModeByRadioButton(iUrbanRadioButton);
selected.add(modeToAdd);
}
#Override
public int getItemCount() {
return modes.size();
}
}
Thank you in advance.

Ok guys, I just to solve that, I was calling notifyDataSetChanged() from the class which contain the Adapter. This is because the recyclerView were refreshing all the times and the checkboxes and radiobuttons don't be printed as checked.
The solution that works to me is calling the notifyDataSetChanged() inside the recyclerView. Just like this:
checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//My code...
notifyDataSetChanged();
}
});

Related

How to get data from nested Recycler View having CheckBox?

Actually this screen displays a set of questions and the task is to read the user entered or selected answer.
So the my question is, how to get the value from ChooseAdapter to QuestionAdapter and then get all the value from QuestionAdapter to my Activity.
My english is little bit weak, sorry for that.
And thanks in advance.
Main adapter : QuestionAdapter.java
public class QuestionsAdapter extends RecyclerView.Adapter<QuestionsAdapter.RecyclerViewHolder> {
private ArrayList<Question> mRecyclerViewItems;
private static final int MENU_ITEM_VIEW_TYPE = 0;
private static final String TAG = QuestionsAdapter.class.getSimpleName();
private static Context mContext;
private NetworkManager nm;
private boolean visibility = false;
private ChoiceAdapter adapter;
private ArrayList<QuestionsAnswer> questionsAnswers = new ArrayList<>();
ArrayList<ChoiceAnswer> choiceAnswers;
public QuestionsAdapter(Context context, ArrayList<Question> recyclerViewItems) {
this.mContext = context;
this.mRecyclerViewItems = recyclerViewItems;
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//this view contains recycler view under recycler view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_question, parent, false);
RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(v);
return recyclerViewHolder;
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case MENU_ITEM_VIEW_TYPE:
default:
final RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder;
Question data = (Question) mRecyclerViewItems.get(position);
try {
recyclerViewHolder.txtQuestion.setText(data.getQuestion());
recyclerViewHolder.txtQuestionType.setText(data.getQuestionType());
if (data.getQuestionType().equals("MULT")) {
recyclerViewHolder.mRecyclerChoice.setVisibility(View.VISIBLE);
recyclerViewHolder.edtQuestion.setVisibility(View.GONE);
if (data.getChoices().size() > 0) {
adapter = new ChoiceAdapter(mContext, data.getChoices(), position);
recyclerViewHolder.mRecyclerChoice.setAdapter(adapter);
}
} else {
recyclerViewHolder.mRecyclerChoice.setVisibility(View.GONE);
recyclerViewHolder.edtQuestion.setVisibility(View.VISIBLE);
}
recyclerViewHolder.btnOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (data.getQuestionType().equals("MULT")) {
Log.v(TAG, "array Data : " + adapter.getChoiceAnswer());
} else {
Log.v(TAG, "array Data : " + recyclerViewHolder.edtQuestion.getText().toString());
}
}
});
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
#Override
public int getItemCount() {
return mRecyclerViewItems.size();
}
class RecyclerViewHolder extends RecyclerView.ViewHolder {
TextView txtQuestion,txtQuestionType;
EditText edtQuestion;
RecyclerView mRecyclerChoice;
Button btnOk;
private LinearLayoutManager linearLayoutManager;
public RecyclerViewHolder(View view) {
super(view);
txtQuestion = view.findViewById(R.id.txt_question);
edtQuestion = view.findViewById(R.id.edt_question);
mRecyclerChoice = view.findViewById(R.id.recycler_choice);
btnOk = view.findViewById(R.id.btn_ok);
txtQuestionType = view.findViewById(R.id.txt_question_type);
initRecyclerView();
btnOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (txtQuestionType.getText().toString().equals("MULT")) {
Log.v(TAG, "array Data : " + adapter.getChoiceAnswer());
} else {
Log.v(TAG, "array Data : " + edtQuestion.getText().toString());
}
}
});
}
private void initRecyclerView() {
//setting properties of recyclerView
mRecyclerChoice.setHasFixedSize(true);
mRecyclerChoice.setHasFixedSize(true);
linearLayoutManager = new LinearLayoutManager(mContext);
mRecyclerChoice.setLayoutManager(linearLayoutManager);
}
}
public static void validation() {
Toast.makeText(mContext, "testing", Toast.LENGTH_SHORT).show();
}}
for list of CheckBox : ChooseAdapter.java
public class ChoiceAdapter extends RecyclerView.Adapter<ChoiceAdapter.RecyclerViewHolder> {
private ArrayList<Choice> mRecyclerViewItems;
private static final int MENU_ITEM_VIEW_TYPE = 0;
private static final String TAG = ChoiceAdapter.class.getSimpleName();
private Context mContext;
private NetworkManager nm;
// private OnItemClickListener mOnItemClickListener;
private boolean visibility = false;
private static ArrayList<ChoiceAnswer> choiceAnswerArrayList;
private ChoiceAnswer choiceAnswer;
String arrayData;
public ChoiceAdapter(Context context, ArrayList<Choice> recyclerViewItems, int position) {
this.mContext = context;
this.mRecyclerViewItems = recyclerViewItems;
// choiceAnswer.key = 0;
choiceAnswerArrayList = new ArrayList<>();
//initializing choiceAnswer
choiceAnswer = new ChoiceAnswer();
choiceAnswer.values = new ArrayList<>();
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//this view contains recycler view under recycler view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_radio_button, parent, false);
RecyclerViewHolder recyclerViewHolder = new RecyclerViewHolder(v);
return recyclerViewHolder;
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
int viewType = getItemViewType(position);
switch (viewType) {
case MENU_ITEM_VIEW_TYPE:
default:
final RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder;
Choice data = (Choice) mRecyclerViewItems.get(position);
try {
recyclerViewHolder.checkChoice.setText(data.getChoiceName());
recyclerViewHolder.checkChoice.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
arrayData = "";
for (int i = 0; i < mRecyclerViewItems.size(); i++) {
if (isChecked) {
if (!choiceAnswer.values.contains(data.getChoiceID())) {
choiceAnswer.values.add(i, data.getChoiceID());
}
} else {
choiceAnswer.values.remove(data.getChoiceID());
// arrayData = choiceAnswer.values.toString().replace("[", "").replace("]", "").trim();
}
try {
arrayData = arrayData + "," + choiceAnswer.values.get(i);
}catch (IndexOutOfBoundsException e){
e.printStackTrace();
}
}
}
});
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}
public String getChoiceAnswer() {
return arrayData;
}
#Override
public int getItemCount() {
return mRecyclerViewItems.size();
}
class RecyclerViewHolder extends RecyclerView.ViewHolder {
CheckBox checkChoice;
public RecyclerViewHolder(View view) {
super(view);
checkChoice = view.findViewById(R.id.check_choice);
}
}}
Please help me guys I am trying this since last 3 days...
I've implemented my own login too, but it didn't working properly.

How to manage multiple positions in RecyclerView OnClickListener

I want to know how I can get access to other elements of the array in this onclicklistener for a Recycler view. Specifically, I want to be able to change the enabled state of a position other than the current Listener position, but within the click event.
I'm trying to make it such that if three colors are checked (those are check boxes) every box not checked will be disabled until the number of boxes checked is < 3.
The for-loops I have I wrote make sense, but I can't programmatically change the enabled state within the onClickListener for some reason.
private void buildRecyclerView() {
mRecyclerView = findViewById(R.id.recyclerView);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new ExampleAdapter(mExampleList);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
boolean checkedState;
if (mExampleList.get(position).getChecked1() == false) {
checkedState = true;
} else {
checkedState = false;
}
changeItem(position, checkedState);
int sum = 0;
for (int i = 0; i < stringArray.length; i++) {
Boolean checked = mExampleList.get(i).getChecked1();
if (checked == true) {
sum = sum + 1;
}
}
for (int i = 0; i < stringArray.length; i++) {
Boolean checked = mExampleList.get(i).getChecked1();
if (!checked && sum == 3) {
mExampleList.get(i).setEnabled1(false);
} else {
mExampleList.get(i).setEnabled1(true);
}
}
}
});
}
adapter
public class ExampleAdapter extends RecyclerView.Adapter<ExampleAdapter.ExampleViewHolder> {
private ArrayList<ExampleItem> mExampleList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class ExampleViewHolder extends RecyclerView.ViewHolder {
public CheckBox mCheckBox;
public ExampleViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mCheckBox = itemView.findViewById(R.id.checkBox);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null){
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION);
listener.onItemClick(position);
}
}
});
}
}
public ExampleAdapter(ArrayList<ExampleItem> exampleList) {
mExampleList = exampleList;
}
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.example_item, parent, false);
ExampleViewHolder evh = new ExampleViewHolder(v, mListener);
return evh;
}
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mCheckBox.setText(currentItem.getCheckText());
holder.mCheckBox.setEnabled(currentItem.getEnabled1());
holder.mCheckBox.setChecked(currentItem.getChecked1());
}
#Override
public int getItemCount() {
return mExampleList.size();
}
}
Item Class
public class ExampleItem {
public String mCheckText;
public Boolean mEnabled;
public Boolean mChecked;
public ExampleItem(String mCheckText, Boolean mEnabled, Boolean mChecked) {
this.mCheckText = mCheckText;
this.mEnabled = mEnabled;
this.mChecked = mChecked;
}
public ExampleItem(String mCheckText) {
this.mCheckText = mCheckText;
}
public String getCheckText() {
return mCheckText;
}
public void setCheckText(String mCheckText) {
this.mCheckText = mCheckText;
}
public Boolean getEnabled1() {
return mEnabled;
}
public void setEnabled1(Boolean mEnabled) {
this.mEnabled = mEnabled;
}
public Boolean getChecked1() {
return mChecked;
}
public void setChecked1(Boolean mChecked) {
this.mChecked = mChecked;
}
}
In other words, I am trying to make everything below blue disabled until I uncheck Red, Green, or Blue!
Try the following:
In adapter, add below codes:
private int selectedCount = 0;
public int getSelectedCount() {
return selectedCount;
}
public void setSelectedCount(int selectedCount) {
this.selectedCount = selectedCount;
notifyDataSetChanged();
}
and change onBindViewHolder() to:
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
ExampleItem currentItem = mExampleList.get(position);
holder.mCheckBox.setText(currentItem.getCheckText());
holder.mCheckBox.setChecked(currentItem.getChecked1());
if ((selectedCount == 3)) holder.mCheckBox.setEnabled(currentItem.getChecked1());
else holder.mCheckBox.setEnabled(true);
}
Then in Activity/Fragment, change mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener()... to:
mAdapter.setOnItemClickListener(new ExampleAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
boolean checkedState;
int selectedCount = mAdapter.getSelectedCount();
if ((selectedCount != 3) || (mExampleList.get(position).getChecked1())) {
if (mExampleList.get(position).getChecked1() == false) {
checkedState = true;
selectedCount++;
} else {
checkedState = false;
selectedCount--;
}
changeItem(position, checkedState);
mAdapter.setSelectedCount(selectedCount);
}
}
});
Pls note that no need to have mEnabled field in the ExampleItem class. Hope that helps!
Explanantion:
About the onClick:- This is because CheckBox totally covered the layout, so itemView cannot recieve the click event. About RecyclerView:- The idea is simple, after modified the data set [not list, here I refer to the mExampleList and also the selectedCount], then call notifyDataSetChanged() which will redraw all recycler item views.
You would need to create a setter function for your 'mExampleList' in your Adpater class, to update the dataset that the adapter is using. It obviously does not change anything, if you make changes to 'mExampleList' in your activity, without updating the list used by the Adapter.
So at the end of your click listener you would have something like that:
mAdapter.setExampleList(mExampleList)
mAdapter.notifyDataSetChanged()

How to prevent the duplication of `RecyclerView` when scrolling?

I am showing a love sign on my RecyclerView.
When user clicked the color of the love sign changes from default gray to red color but when I scrolled it is showing color in some other positions(not clicked). Also the clicked color changes to gray.
I found large number of solutions but nothing worked for me.
Please help.
I am giving you my codes
Featured Products class
public class FeaturedlistAdapter extends RecyclerView.Adapter<FeaturedlistAdapter.FeaturedView>
{
private Context context;
private List<Featured_data> featured_data;
public FeaturedlistAdapter(Context context, List<Featured_data> featured_data,MyAdapterListener myAdapterListener) {
this.context=context;
this.featured_data=featured_data;
this.onclickListener=myAdapterListener;
}
#NonNull
#Override
public FeaturedView onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.list_allbrands, viewGroup, false);
return new FeaturedView(view);
}
#Override
public void onBindViewHolder(#NonNull FeaturedView featuredView, int i) {
String price = featured_data.get(i).getProductPrice();
String name = featured_data.get(i).getProductName();
String quantity = featured_data.get(i).getProductQty();
featuredView.getTxt_brandname().setText(featured_data.get(i).getProductName());
String wishlist=featured_data.get(i).getWishlist();
Picasso.get().load(HomeConstants.BASE_URL + featured_data.get(i).getProductImage()).placeholder(R.drawable.whitebackground).into(featuredView.img_brand);
if (price != null && !price.equals("")) {
String total_price = price + " Rs";
featuredView.getTxt_brand_price().setText(total_price);
}
if (quantity != null && !quantity.equals("")) {
String total_quantity = quantity + " Items";
featuredView.getTxt_brand_item().setText(total_quantity);
}
if(wishlist!=null)
{
if(wishlist.equals("0"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
else if(wishlist.equals("1"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255,255,0,0));
featuredView.txt_count.setText("1");
}
}
else
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
}
#Override
public int getItemCount() {
return featured_data.size();
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
class FeaturedView extends RecyclerView.ViewHolder {
ImageView img_brand,img_wishlist;
TextView txt_brandname,txt_brand_price,txt_brand_item,txt_count;
public ImageView getImg_brand() {
return img_brand;
}
public ImageView getImg_wishlist() {
return img_wishlist;
}
public TextView getTxt_brandname() {
return txt_brandname;
}
public TextView getTxt_brand_price() {
return txt_brand_price;
}
public TextView getTxt_brand_item() {
return txt_brand_item;
}
public TextView getTxt_count() {
return txt_count;
}
FeaturedView(#NonNull View itemView) {
super(itemView);
img_brand=itemView.findViewById(R.id.img_brand);
img_wishlist=itemView.findViewById(R.id.img_wishlist);
txt_brandname=itemView.findViewById(R.id.txt_brandname);
txt_brand_price=itemView.findViewById(R.id.txt_brand_price);
txt_brand_item=itemView.findViewById(R.id.txt_brand_item);
txt_count=itemView.findViewById(R.id.txt_count);
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String value = txt_count.getText().toString();
if (value.equals("0")) {
img_wishlist.setColorFilter(Color.argb(255, 255, 0, 0));
txt_count.setText("1");
} else if (value.equals("1")) {
img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
txt_count.setText("0");
}
onclickListener.wishlistOnclick(v,getAdapterPosition());
}
});
img_brand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onclickListener.brandOnClick(v,getAdapterPosition());
}
});
}
}
private MyAdapterListener onclickListener;
public interface MyAdapterListener
{
void wishlistOnclick(View view ,int position);
void brandOnClick(View view,int position);
}
}
You need to keep the state of the view by using SparseBooleanArray. It is because in RecylerView the item will be shown with the previous view (if exist), i.e the view will be recycled first before used. Hence the mean of RecyclerView.
You can do something like this:
First, in your Adapter, add the SparseBooleanArray to hold the flags (Please read the comment in the code):
public class FeaturedlistAdapter extends RecyclerView.Adapter<FeaturedlistAdapter.FeaturedView>
{
private Context context;
private List<Featured_data> featuredData;
private SparseBooleanArray mSelectedFlags;
public FeaturedlistAdapter(Context context, List<Featured_data> featured_data,MyAdapterListener myAdapterListener) {
...
// init the flag
mSparseBooleanArray = new SparseBooleanArray();
}
#Override
public void onBindViewHolder(#NonNull FeaturedView featuredView, int i) {
int position = featuredView.getAdapterPosition();
Featured_data data = featuredData.get(position);
// reset the state of the view each time the
// view get recycled by applying the flag.
if(mSelectedFlags.get(position)) {
// set the selected state, i.e red
} else {
// SparseBooleanArray.get(i) is false if not found
// set the unselected state, i.e grey
}
}
then in your ViewHolder, set the state when member view is clicked/selected:
class FeaturedView extends RecyclerView.ViewHolder {
...
FeaturedView(#NonNull View itemView) {
...
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
...
// save the selected state
mSparseBooleanArray.put(getAdapterPosition(), true);
}
...
}
}
Now the view selected/unselected state will be reset using the saved stated from your SparseBooleanArray flag holder.
Replace Following Code in your file and try
if(wishlist!=null)
{
if(wishlist.equals("1")) // change is here
{
featuredView.img_wishlist.setColorFilter(Color.argb((255,255,0,0));
featuredView.txt_count.setText("1");
}
else (wishlist.equals("0")) // change is here
{
featuredView.img_wishlist.setColorFilter(Color.argb(255,255,111,111));
featuredView.txt_count.setText("0");
}
}
else
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
Also for this
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
featured_data.get(getAdapterPosition).setWishlist(featured_data.get(getAdapterPosition).getWishlist().equals("0")?"1":"0");
notifyItemChanged(getAdapterPosition());
onclickListener.wishlistOnclick(v,getAdapterPosition());
}
});
public class FeaturedlistAdapter extends RecyclerView.Adapter<FeaturedlistAdapter.FeaturedView>
{
private Context context;
private List<Featured_data> featured_data;
private final SparseBooleanArray mSparseBooleanArray;
public FeaturedlistAdapter(Context context, List<Featured_data> featured_data,MyAdapterListener myAdapterListener) {
this.context=context;
this.featured_data=featured_data;
this.onclickListener=myAdapterListener;
// init the flag
mSparseBooleanArray = new SparseBooleanArray();
}
#NonNull
#Override
public FeaturedView onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.list_allbrands, viewGroup, false);
return new FeaturedView(view);
}
#Override
public void onBindViewHolder(#NonNull FeaturedView featuredView, int i) {
String price = featured_data.get(i).getProductPrice();
String name = featured_data.get(i).getProductName();
String quantity = featured_data.get(i).getProductQty();
featuredView.getTxt_brandname().setText(featured_data.get(i).getProductName());
String wishlist=featured_data.get(i).getWishlist();
Picasso.get().load(HomeConstants.BASE_URL + featured_data.get(i).getProductImage()).placeholder(R.drawable.whitebackground).into(featuredView.img_brand);
if (price != null && !price.equals("")) {
String total_price = price + " Rs";
featuredView.getTxt_brand_price().setText(total_price);
}
if (quantity != null && !quantity.equals("")) {
String total_quantity = quantity + " Items";
featuredView.getTxt_brand_item().setText(total_quantity);
}
if(wishlist!=null)
{
if(wishlist.equals("0"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255, 211, 211, 211));
featuredView.txt_count.setText("0");
}
else if(wishlist.equals("1"))
{
featuredView.img_wishlist.setColorFilter(Color.argb(255,255,0,0));
featuredView.txt_count.setText("1");
}
}
int position=featuredView.getAdapterPosition();
if(mSparseBooleanArray.get(position))
{
String value = featuredView.txt_count.getText().toString();
if (value.equals("0")) {
featuredView.img_wishlist.setColorFilter(Color.argb(255, 255, 0, 0));
// save the selected state
}
else if (value.equals("1")) {
featuredView.img_wishlist.setColorFilter(Color.argb(255,211,211,211));
// save the selected state
}
}
}
#Override
public int getItemCount() {
return featured_data.size();
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
public int getItemViewType(int position) {
return super.getItemViewType(position);
}
class FeaturedView extends RecyclerView.ViewHolder {
ImageView img_brand,img_wishlist;
TextView txt_brandname,txt_brand_price,txt_brand_item,txt_count;
public ImageView getImg_brand() {
return img_brand;
}
public ImageView getImg_wishlist() {
return img_wishlist;
}
public TextView getTxt_brandname() {
return txt_brandname;
}
public TextView getTxt_brand_price() {
return txt_brand_price;
}
public TextView getTxt_brand_item() {
return txt_brand_item;
}
public TextView getTxt_count() {
return txt_count;
}
FeaturedView(#NonNull View itemView) {
super(itemView);
img_brand=itemView.findViewById(R.id.img_brand);
img_wishlist=itemView.findViewById(R.id.img_wishlist);
txt_brandname=itemView.findViewById(R.id.txt_brandname);
txt_brand_price=itemView.findViewById(R.id.txt_brand_price);
txt_brand_item=itemView.findViewById(R.id.txt_brand_item);
txt_count=itemView.findViewById(R.id.txt_count);
img_wishlist.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String value = txt_count.getText().toString();
if (value.equals("0")) {
img_wishlist.setColorFilter(Color.argb(255, 255, 0, 0));
txt_count.setText("1");
} else if (value.equals("1")) {
img_wishlist.setColorFilter(Color.argb(255,211,211,211));
txt_count.setText("0");
}
onclickListener.wishlistOnclick(v,getAdapterPosition());
mSparseBooleanArray.put(getAdapterPosition(), true);
notifyDataSetChanged();
}
});
img_brand.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onclickListener.brandOnClick(v,getAdapterPosition());
}
});
}
}
private MyAdapterListener onclickListener;
public interface MyAdapterListener
{
void wishlistOnclick(View view ,int position);
void brandOnClick(View view,int position);
}
}

Multi selection in RecyclerView?

Hello I am trying to implement multi select in recycler view android for showing an icon when clicked on that particular view, I have tried the below code and is working fine for that particular position, however there are other several views that too are getting updated, so please check and let me know what am I missing
Here is my adapter code:
public class ContactsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
Context context;
ArrayList<String> alContactName, alContactEmail, alContactNumber;
ArrayList<Boolean> alFromLinkedIn;
int mergeFlag=0;
private static SparseBooleanArray selectedItems;
ArrayList<Integer> alSelectedPositions;
public ContactsAdapter(Context context, ArrayList<String> alContactName, ArrayList<String> alContactEmail, ArrayList<String> alContactNumber, ArrayList<Boolean> alisFromLinkedIn) {
//Include one more variable for checking type i.e linked in or normal contact
super();
this.context = context;
this.alContactName = alContactName;
this.alContactEmail = alContactEmail;
this.alContactNumber = alContactNumber;
this.alFromLinkedIn = alisFromLinkedIn;
alSelectedPositions=new ArrayList<>();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(context);
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_merge_contact, parent, false);
return new ContactsHolder(view);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
try {
((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
alSelectedPositions.add(position);
notifyDataSetChanged();
}
});
if(alSelectedPositions.get(position)==position){
((ContactsHolder) holder).imgMerge.setVisibility(View.VISIBLE);
}
else {
((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
}
} catch (Exception e) {
e.printStackTrace();
}
}
check updated code. I have modified the #tahsinRupam code.
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
try {
((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(alSelectedPositions.size>0)
{
for(int i=0;i<a1SelectedPositions.size;i++)
{
//if you want to cleasr previous details of array
if(a1SelectedPositions.contains(position))
alSelectedPositions.remove(position);
else
alSelectedPositions.add(position);
}
}
else
{
alSelectedPositions.add(position);
notifyDataSetChanged();
}
});
//update the position on scroll
for(int i=0;i<a1SelectedPositions.size;i++)
{
if(alSelectedPositions.get(i)==position){
((ContactsHolder)holder).imgMerge.setVisibility(View.VISIBLE);
}
else {
((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Recently I had to implement a multi select RecyclerView, below I attached a simplified code snippet for a clean way to implement multi-select feature in RecyclerView:
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemHolder> implements IMultiSelectableList<Item> {
boolean selectionMode = false;
HashSet<Item> selectedItems;
ArrayList<Item> mItems;
public ItemAdapter(ArrayList<Item> Items) {
super();
selectedItems = new HashSet<>();
mItems = Items;
}
public void enterSelectionModeWithItem(int selectedItemPosition){
if(selectedItemPosition >= 0 && selectedItemPosition < mItems.size())
selectedItems.add(mItems.get(selectedItemPosition));
selectionMode = true;
notifyDataSetChanged();
}
public void clearSelectionMode() {
selectionMode = false;
selectedItems.clear();
notifyDataSetChanged();
}
public class ItemHolder extends RecyclerView.ViewHolder{
ImageView mImage;
public ItemHolder(View itemView) {
super(itemView);
mImage = itemView.findViewById(R.id.image);
itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
if(!selectionMode){
int selectedPosition = getAdapterPosition();
Item selectedItem = mItems.get(selectedPosition);
enterSelectionModeWithItem(selectedItem);
return true;
}
return false;
}
});
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int selectedPosition = getAdapterPosition();
Item selectedItem = mItems.get(selectedPosition);
//Capture Clicks in Selection Mode
if(selectionMode){
if(selectedItems.contains(selectedItem)){
selectedItems.remove(selectedItem);
mImage.setImageResource(R.drawable.ic_checkbox_blank_circle_outline_grey600_48dp);
} else {
selectedItems.add(selectedItem);
mImage.setImageResource(R.drawable.ic_checkbox_marked_circle_grey600_48dp);
}
}
}
});
}
public void setupView(Item item){
if(selectionMode){
if(selectedItems.contains(item)){
mImage.setImageResource(R.drawable.ic_checkbox_marked_circle_grey600_48dp);
} else {
mImage.setImageResource(R.drawable.ic_checkbox_blank_circle_outline_grey600_48dp);
}
}
}
#Override
public ItemAdapter.ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cell_item, parent, false);
return new ItemHolder(view);
}
#Override
public void onBindViewHolder(ItemAdapter.ItemHolder holder, int position) {
holder.setupView(mItems.get(position));
}
#Override
public int getItemCount() {
return mItems != null ? mItems.size() : 0;
}
}
, I use an image to show selection like Gmail app but feel free to use whatever works for you (background color, font style, etc).
P.S: I designed a callback interface for a simple selection interactions, if it helps I can attach it too! Cheers!
You've to do some specific things:
Initialize an int type array (type can be different) and assign 0 value to all it's elements.
int[] selectedPos = null;
public ContactsAdapter(Context context, ArrayList<String> alContactName, ArrayList<String> alContactEmail, ArrayList<String> alContactNumber, ArrayList<Boolean> alisFromLinkedIn) {
//Include one more variable for checking type i.e linked in or normal contact
super();
this.context = context;
this.alContactName = alContactName;
this.alContactEmail = alContactEmail;
this.alContactNumber = alContactNumber;
this.alFromLinkedIn = alisFromLinkedIn;
alSelectedPositions=new ArrayList<>();
for(int i = 0 ; i < alContactName.size() ; i++)
selectedPos[i] = 0;
}
Store the selected positions in selectedPos.
Then, check if the position is selected and set visibility accordingly:
In onBindViewHolder() add the following code:
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
try {
((ContactsHolder) holder).relMain.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectedPos[position] = 1;
notifyDataSetChanged();
}
});
} catch (Exception e) {
e.printStackTrace();
}
// Checking if the position was selected
if(selectedPos[position] == 1)
((ContactsHolder) holder).imgMerge.setVisibility(View.VISIBLE);
else
((ContactsHolder) holder).imgMerge.setVisibility(View.GONE);
}
I have resolved my issue here is the code if it could help someone:
#Override
public ContactsHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_merge_contact, parent, false);
final ContactsHolder holder = new ContactsHolder(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (holder.getAdapterPosition() != RecyclerView.NO_POSITION) {
mSelectedItemPosition = holder.getAdapterPosition();
//notifyItemChanged(holder.getAdapterPosition());
notifyDataSetChanged();
}
}
});
return holder;
}
#Override
public void onBindViewHolder(ContactsHolder holder, int position) {
try {
if (mSelectedItemPosition == position) {
if (mergeFlag != 1) {
holder.imgMerge.setVisibility(View.VISIBLE);
mergeFlag = 1;
selectdParentId = contactsModels.get(position).alContactIdList;
} else{
//holder.relDone.setVisibility(View.GONE);
if (!selectdParentId.equals(contactsModels.get(position).alContactIdList)) {
holder.relDone.setVisibility(View.VISIBLE);
alChildId.add(contactsModels.get(position).alContactIdList);
} else {
holder.imgMerge.setVisibility(View.VISIBLE);
}
}
} else {
holder.imgMerge.setVisibility(View.GONE);
holder.relDone.setVisibility(View.GONE);
}
}

How to add sections for checked and unchecked items in recyclerview?

I have a list of tasks in recyclerview. Each task item has a check box to show if the task is completed or pending.
Now I want to show two sections in my list. One for checked items and another for unchecked items.
I have gone through this library to add the sections.
https://github.com/afollestad/sectioned-recyclerview
But how can I divide the items in list on the basis of they are checked or not?
Also I want to add the task into another section if checked or unchecked , i.e onClick.
If task is unchecked, and if I check it, it should get added to the completed section and vise versa.
I have a recyclerview now with swipe layout. Following is the adapter.
adapetr:
public class IAdapter extends RecyclerSwipeAdapter<IAdapter.ItemViewHolder> , SectionedRecyclerViewAdapter<IAdapter.ItemViewHolder> {
public ArrayList<Task> items;
Context conext;
public int _mId;
List<Task> itemsPendingRemoval = new ArrayList<>();
public IAdapter(Context context, ArrayList<Task> item) {
this.conext=context;
this.items=item;
}
#Override
public int getSectionCount() {
return 2;
}
#Override
public int getItemCount(int section) {
return items.size();
}
public static class ItemViewHolder extends RecyclerView.ViewHolder {
Task task;
CheckBox cb;
SwipeLayout swipeLayout;
TaskTableHelper taskTableHelper;
ItemViewHolder(final View itemView) {
super(itemView);
taskTableHelper= new TaskTableHelper(itemView.getContext());
swipeLayout = (SwipeLayout) itemView.findViewById(R.id.swipe);
cb = (CheckBox) itemView.findViewById(R.id.checkbox);
}
}
#Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder,final int i) {
itemViewHolder.cb.setText(items.get(i).getTitle());
itemViewHolder.task = items.get(i);
int taskId = itemViewHolder.task.getId();
itemViewHolder.task = itemViewHolder.taskTableHelper.getTask(taskId);
int status = itemViewHolder.task.getStatus();
if(status == 0)
{
itemViewHolder.cb.setTextColor(Color.WHITE);
}
else {
itemViewHolder.cb.setChecked(true);
itemViewHolder.cb.setTextColor(Color.parseColor("#B0BEC5"));
}
itemViewHolder.cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
itemViewHolder.cb.setTextColor(Color.parseColor("#B0BEC5"));
itemViewHolder.task.setStatus(1);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
}
else
{
itemViewHolder.cb.setTextColor(Color.WHITE);
itemViewHolder.task.setStatus(0);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
}
}
});
final Task item = items.get(i);
itemViewHolder.swipeLayout.addDrag(SwipeLayout.DragEdge.Right,itemViewHolder.swipeLayout.findViewById(R.id.bottom_wrapper_2));
itemViewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
itemViewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
#Override
public void onDoubleClick(SwipeLayout layout, boolean surface) {
Toast.makeText(conext, "DoubleClick", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.findViewById(R.id.trash2).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mItemManger.removeShownLayouts(itemViewHolder.swipeLayout);
items.remove(i);
notifyItemRemoved(i);
notifyItemRangeChanged(i, items.size());
mItemManger.closeAllItems();
itemViewHolder.taskTableHelper.deleteTask(item);
_mId = item.getAlertId();
cancelNotification();
Toast.makeText(view.getContext(), "Deleted " + itemViewHolder.cb.getText().toString() + "!", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.findViewById(R.id.done).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemViewHolder.task.setStatus(1);
itemViewHolder.taskTableHelper.updateStatus(itemViewHolder.task);
itemViewHolder.cb.setChecked(true);
Toast.makeText(conext, "Task Completed.", Toast.LENGTH_SHORT).show();
}
});
itemViewHolder.swipeLayout.getSurfaceView().setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean mEditMode;
int id = item.getId();
int priority = item.getTaskPriority();
String title = item.getTitle();
String alertDate = item.getAlertDate();
String alertTime = item.getAlertTime();
String dueDate = item.getDueDate();
String dueTime = item.getDueTime();
_mId = item.getAlertId();
int listId = item.getList();
mEditMode = true;
Intent i = new Intent(conext, AddTaskActivity.class);
i.putExtra("taskId", id);
i.putExtra("taskTitle", title);
i.putExtra("taskPriority", priority);
i.putExtra("taskAlertTime", alertTime);
i.putExtra("taskAlertDate", alertDate);
i.putExtra("taskDueDate", dueDate);
i.putExtra("taskDueTime", dueTime);
i.putExtra("taskListId", listId);
i.putExtra("EditMode", mEditMode);
i.putExtra("AlertId",_mId);
conext.startActivity(i);
}
});
mItemManger.bindView(itemViewHolder.itemView, i);
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup,int position) {
View itemView = LayoutInflater.
from(viewGroup.getContext()).
inflate(R.layout.card_layout, viewGroup, false);
return new ItemViewHolder(itemView);
}
#Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
public void remove(int position) {
Task item = items.get(position);
if (itemsPendingRemoval.contains(item)) {
itemsPendingRemoval.remove(item);
}
if (items.contains(item)) {
items.remove(position);
notifyItemRemoved(position);
}
}
public void cancelNotification()
{
AlarmManager alarmManager = (AlarmManager)conext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(conext, NotificationReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(conext,_mId, intent, 0);
alarmManager.cancel(pendingIntent);
}
#Override
public int getSwipeLayoutResourceId(int position) {
return R.id.swipe;
}
}
Can anyone help please?
Thank you..
You can add "sections" to your recyclerview with the library SectionedRecyclerViewAdapter.
First create a Section class to group your tasks:
class TaskSection extends StatelessSection {
String title;
List<Task> list;
public TaskSection(String title, List<Task> list) {
// call constructor with layout resources for this Section header, footer and items
super(R.layout.section_header, R.layout.section_item);
this.title = title;
this.list = list;
}
#Override
public int getContentItemsTotal() {
return list.size(); // number of items of this section
}
public int addTask(Task task) {
return list.add(task;
}
public int removeTask(Task task) {
return list.remove(task;
}
#Override
public RecyclerView.ViewHolder getItemViewHolder(View view) {
// return a custom instance of ViewHolder for the items of this section
return new MyItemViewHolder(view);
}
#Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
MyItemViewHolder itemHolder = (MyItemViewHolder) holder;
// bind your view here
itemHolder.tvItem.setText(list.get(position).getTitle());
}
#Override
public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
return new SimpleHeaderViewHolder(view);
}
#Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
MyHeaderViewHolder headerHolder = (MyHeaderViewHolder) holder;
// bind your header view here
headerHolder.tvItem.setText(title);
}
}
Then you set up the RecyclerView with your Sections:
// Create an instance of SectionedRecyclerViewAdapter
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();
// Create your sections with the list of data
TaskSection compSection = new TaskSection("Completed", compList);
TaskSection pendSection = new TaskSection("Pending", pendList);
// Add your Sections to the adapter
sectionAdapter.addSection(compSection);
sectionAdapter.addSection(pendSection);
// Set up your RecyclerView with the SectionedRecyclerViewAdapter
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);
Now if you want to send a task from "Pending" section to "Completed":
pendSection.removeTask(task);
compSection.addTask(task);
sectionAdapter.notifyDataSetChanged();
Regarding to the SwipeLayout, don't extend RecyclerSwipeAdapter, extend SectionedRecyclerViewAdapter and implement the SwipeLayout in ItemViewHolder / onBindItemViewHolder as you have done.

Categories

Resources