I would like to check the property of one of the items in RecyclerView. To be more specific I want to check if this item is selected.
Firstly I select the item
onView(withId(R.id.list_master))
.perform(
RecyclerViewActions.actionOnItemAtPosition(14, clickAnItem(R.id.layout_menu))
);
Secondly check if the specific item is selected:
onView(allOf(withId(R.id.layout_menu), hasDescendant(withText("SO"))))
.check(matches(isSelected()));
With custom matcher:
private static Matcher<View> isSelected() {
return new TypeSafeMatcher<View>() {
#Override
protected boolean matchesSafely(View item) {
return item.isSelected();
}
#Override
public void describeTo(Description description) {
description.appendText("Selected property");
}
};
Sadly the state of this view is not selected, but UI shows it successfully marked as selected item. Implementation details
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.itemView.setSelected(position == selected);
Check this code I had the same thing want you want check whether the field is selected or not in Recycler View.
public class AutoWithRuleListListAdapter extends RecyclerView.Adapter<AutoWithRuleListListAdapter.ViewHolder> {
private Context context;
private Fragment fragment;
private ArrayList<ObjGetLookupDataResponseIn> lookupData;
public AutoWithRuleListListAdapter(Context context, Fragment fragment, ArrayList<ObjGetLookupDataResponseIn> lookupData) {
this.context = context;
this.fragment = fragment;
this.lookupData = lookupData;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.auto_withdraw_ben_name_list, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, #SuppressLint("RecyclerView") final int position) {
String output = lookupData.get(position).getDisplayName().substring(0, 1).toUpperCase() + lookupData.get(position).getDisplayName().substring(1);
holder.radioBen.setText(output);
holder.radioBen.setOnCheckedChangeListener(null);
holder.radioBen.setChecked(lookupData.get(position).isSelected());
holder.radioBen.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
resetAll();
lookupData.get(position).setSelected(true);
notifyDataSetChanged();
((AutoViewRuleFragment)fragment).ruleName(position);
}
});
}
private void resetAll() {
for (int i=0;i<lookupData.size();i++)
{
lookupData.get(i).setSelected(false);
}
notifyDataSetChanged();
}
#Override
public int getItemCount() {
return lookupData.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
RadioButton radioBen;
public ViewHolder(View itemView) {
super(itemView);
radioBen = (RadioButton) itemView.findViewById(R.id.radioReceivesFunds);
radioBen.setTypeface(Utils.gothamMedium);
}
}}
rulename method in my fragment through which i get the position of the view.Add boolean selected in your POJO if this item is selected or not.
Hope this help.Happy Coding.Vote if you find it useful.
Related
My Title is kind of hard to understand but basically when I add items into my database is should display it in a RecyclerView. Now in my RecyclerView I have two layouts but the problem is the first item of my database goes behind my first item in my other layout. So if I have 3 items in my database, it shows only 2 items from the database and the first item hides behind my first item in the RecyclerView which is a different layout that does not use the database at all.
This is my code:
FirebaseRecyclerOptions<Event> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Event>()
.setQuery(query1, Event.class).build();
AccAdapter = new FirebaseRecyclerAdapter<Event, RecyclerView.ViewHolder>(firebaseRecyclerOptions){
final static int TYPE_HEADER = 0;
final static int TYPE_ITEM = 1;
#Override
public int getItemViewType(int position) {
if (position == 0) return TYPE_HEADER;
return TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER){
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_add_items,
parent, false);
return new ProdudctHolder3(view);
} else {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_acc,
parent, false);
return new ProductHolder2(view);
}
}
#Override
protected void onBindViewHolder(final RecyclerView.ViewHolder holder, int position, final Event model) {
if (holder instanceof ProdudctHolder3){
((ProdudctHolder3) holder).addBackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(), AccAddItems.class ));
}
});
} else{
final ProductHolder2 productHolder2 = (ProductHolder2) holder;
productHolder2.mName.setText(model.getName());
productHolder2.view.setBackgroundResource(getBackgroundDrawable(Integer.valueOf(model.getProductAmount())));
productHolder2.mbackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.popup_edit_product);
SeekBar amountSeekBar = dialog.findViewById(R.id.amountSeekBar);
amountSeekBar.setMax(100);
amountSeekBar.setProgress(Integer.valueOf(model.getProductAmount()));
amountSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
progress = i;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
getRef(holder.getAdapterPosition()).child("productAmount").setValue(String.valueOf(progress));
dialog.dismiss();
}
});
dialog.show();
}
});
productHolder2.mbackground.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
final PopupMenu popupMenu = new PopupMenu(getActivity(), productHolder2.mbackground);
popupMenu.inflate(R.menu.menu_acc);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.deleteProduct:
getRef(productHolder2.getAdapterPosition()).removeValue();
popupMenu.dismiss();
return true;
default:
return false;
}
}
});
popupMenu.show();
return true;
}
});
}
}
};
mAccRecyclerViewRef.setAdapter(AccAdapter);
My two Product Holders
private class ProdudctHolder3 extends RecyclerView.ViewHolder{
private RelativeLayout addBackground;
public ProdudctHolder3(View itemView) {
super(itemView);
addBackground = itemView.findViewById(R.id.mBackground2);
}
}
private class ProductHolder2 extends RecyclerView.ViewHolder{
private TextView mName;
private RelativeLayout mbackground;
private View view;
public ProductHolder2(View itemView) {
super(itemView);
mName = itemView.findViewById(R.id.ItemName);
mbackground = itemView.findViewById(R.id.mBackground1);
view = itemView.findViewById(R.id.amountIndicator);
}
}
The ideal solution would have been to set two adapters on a single RecyclerView but unfortunatelly this is not possible.
However, you can make a single custom Adapter that handles two types of items. I will explain this by getting an example.
Let's assume you need to display objects of two types, humans and aliens. Your objects require completely different layouts and completely different ViewHolders. Please see the below code for the ViewHolders:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static class HumanViewHolder extends RecyclerView.ViewHolder {
public HumanViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Human human) {
//Display your human object
}
}
private static class AlienViewHolder extends RecyclerView.ViewHolder {
public AlienViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Alien alien) {
//Display your alien object
}
}
}
First you need to add two different constants to your adapter representing both type of views:
private static final int ITEM_TYPE_HUMAN;
private static final int ITEM_TYPE_ALIEN;
To keep things simple, let's also assume you store your objects in a list:
private List<Object> items = new ArrayList<>();
public MyAdapter(List<Object> items) {
this.items.addAll(items);
//Other stuff if needed
}
Now, the first you need to do, is to implement getItemViewType() method:
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof Human) {
return ITEM_TYPE_HUMAN;
} else {
return ITEM_TYPE_ALIEN;
}
}
Second, you need to use the item type inside the onCreateViewHolder() method like this:
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if (viewType == ITEM_TYPE_HUMAN) {
View view = layoutInflater.inflate(R.layout.item_human, parent, false);
return new HumanViewHolder(view);
} else {
View view = layoutInflater.inflate(R.layout.item_alien, parent, false);
return new AlienViewHolder(view);
}
}
In the end, you just need to bind the proper view holder like this:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
Object item = items.get(position);
if (viewHolder instanceof HumanViewHolder) {
((HumanViewHolder) viewHolder).bind((Human) item);
} else {
((AlienViewHolder) viewHolder).bind((Alien) item);
}
}
Why use the Firebase Recycler Adapter when you could easily make a custom one? If I understood well you want an item to be fixed at position 0 (header) while others will be added below the first one, right? If so, here is a solution I like to use:
public interface ViewType {
public int getViewType();
}
public interface ViewTypeDelegateAdapter {
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item);
}
public class ViewTypes {
public static int HEADER = 0
public static int ITEM = 1
}
public class ProductDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new ProductHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as ProductHolder).bind("test");
}
class ProductHolder extends RecyclerView.ViewHolder {
public ProductHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class HeaderDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new HeaderHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as HeaderHolder).bind("test");
}
class HeaderHolder extends RecyclerView.ViewHolder {
public HeaderHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class AccAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private Context context;
private List<ViewType> items;
private SparseArrayCompat<ViewTypeDelegateAdapter> delegateAdapters;
private ViewType headerItem;
public AccAdapter(Context context) {
this.context = context;
this.items = new ArrayList();
this.delegateAdapters = new SparseArrayCompat();
this.headerItem = new ViewType() {
#Override
public int getViewType() {
return ViewTypes.HEADER;
}
};
this.items.add(this.headerItem);
this.delegateAdapters.put(ViewTypes.HEADER, HeaderDelegateAdapter(R.id.test, this.context));
this.delegateAdapters.put(ViewTypes.ITEM, ProductDelegateAdapter(R.id.test, this.context));
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {
return delegateAdapters.get(viewType).onCreateViewHolder(parent);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, Int position) {
delegateAdapters.get(getItemViewType(position)).onBindViewHolder(holder, items[position])
}
#Override
public Int getItemViewType(Int position) {
return items.get(position).getViewType();
}
#Override
public Int getItemCount() {
return items.getSize();
}
public void add(ViewType viewType) {
val initPosition = this.items.size - 1
this.items.add(item)
notifyItemRangeChanged(initPosition, this.items.size + 1)
}
}
public class Event implements ViewType {
private String id;
#Override
public int getViewType() {
return ViewTypes.ITEM;
}
}
Excuse me for some syntax errors, I've translated to Java from Kotlin to help you. Hope it helps!
I have a RecyclerView and each CardView contains a TextView and an ImageView. Whenever I click an item, I want to set the image visibility to VISIBLE and to set the previous clicked item image's visibility to INVISIBLE.
This is my Adapter class :
public class CategoryAdapter extends RecyclerView.Adapter<CategoryAdapter.ViewHolder>{
private Context context;
private List<Category> lista;
private LayoutInflater layoutInflater;
private IncomeCategoryActivity activity;
private static final int CATEGORY_REQUEST=6;
private static final int ITEM_EDIT=1;
private static final int ITEM_DELETE=2;
private static final int EDIT_REQUEST=7;
private int current_pos=-1;
public CategoryAdapter(List<Category> lista, Context context, IncomeCategoryActivity activity) {
this.context = context;
this.lista = lista;
this.activity=activity;
layoutInflater=LayoutInflater.from(context);
}
#Override
public CategoryAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=layoutInflater.inflate(R.layout.category_layout, parent, false);
ViewHolder viewHolder=new ViewHolder(view, activity);
return viewHolder;
}
#Override
public void onBindViewHolder(CategoryAdapter.ViewHolder holder, int position) {
holder.imageView.setImageURI(lista.get(position).getUri());
holder.textView.setText(lista.get(position).getCategory());
holder.position = position;
holder.category=lista.get(position);
if(holder.category.isChecked()==true){
holder.imageViewCheck.setVisibility(View.VISIBLE);
current_pos=position;
} else {
holder.imageViewCheck.setVisibility(View.INVISIBLE);
}
}
#Override
public int getItemCount() {
return lista.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener{
public ImageView imageView;
public TextView textView;
public ImageView imageViewCheck;
public int position;
public Category category;
public IncomeCategoryActivity activity;
public ViewHolder(View itemView, IncomeCategoryActivity activity) {
super(itemView);
this.activity=activity;
imageView=itemView.findViewById(R.id.customCategoryImageView);
textView=itemView.findViewById(R.id.customCategoryTextView);
imageViewCheck=itemView.findViewById(R.id.customCheckImageView);
itemView.setOnClickListener(this);
itemView.setOnCreateContextMenuListener(this);
}
#Override
public void onClick(View v) {
String aux=textView.getText().toString();
if(aux=="CATEGORIE NOUĂ"){
Intent intent=new Intent(context, CustomIncomeActivity.class);
activity.startActivityForResult(intent, CATEGORY_REQUEST);
}
else{
imageViewCheck.setVisibility(View.VISIBLE);
int pozitie_check=getLayoutPosition();
Intent intent=new Intent(context, AddIncomeActivity.class);
intent.putExtra("categorie_venit", aux);
intent.putExtra("position_check", pozitie_check);
activity.setResult(Activity.RESULT_OK, intent);
activity.finish();
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle("Selectează acțiunea");
MenuItem edit=menu.add(0, ITEM_EDIT, 0, "Modifică");
MenuItem delete=menu.add(0, ITEM_DELETE, 0, "Șterge");
edit.setOnMenuItemClickListener(this);
delete.setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
int position=getLayoutPosition();
if (item.getGroupId() == 0) {
if(item.getItemId()==ITEM_EDIT){
Category category=lista.get(position);
Intent intent=new Intent(activity, CustomIncomeActivity.class);
intent.putExtra("edit_icon", category.getUri());
intent.putExtra("edit_category", category.getCategory());
intent.putExtra("list_position", position);
activity.startActivityForResult(intent, EDIT_REQUEST);
}
else if(item.getItemId()==ITEM_DELETE){
lista.remove(position);
notifyDataSetChanged();
}
}
return true;
}
At this moment, whenever I click an item, there are two images VISIBLE on the RecyclerView: the clicked item's image and the previous clicked item's image. I think I need to get the previous View by its position and to manually set the visibility to INVISIBLE.
recycleView.getChildCount() and recycleView_parent.getChildAt() only gives the Adapter items which is shows only screen .
that means if your list has 200 items and the only 5 items shows on screen so we can find only 5 item with the help of recycleView
i am using one simple trick to solve the issue.
You can define Hashmap which hold your holder objects
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
ArrayList<Model> dataList;
Context context;
HashMap<Integer,ViewHolder> holderlist;
public MyAdapter(ArrayList<Model> dataList, Context context) {
this.context = context;
this.dataList = dataList;
holderlist = new HashMap<>();
}
And after that to save the holder in Hashmap
public void onBindViewHolder(final ViewHolder holder, final int position) {
if(!holderlist.containsKey(position)){
holderlist.put(position,holder);
}
Create a method in Adapter.
public MyListAdapter.ViewHolder getViewByPosition(int position) {
return holderlist.get(position);
}
Call this method from your Activity or whenever you want.
for (int i = 0; i < datalList.size(); i++) {
MyAdapter.ViewHolder holder = ((MyAdapter)recycleView.getAdapter()).getViewByPosition(i);
View view = holder.itemView;
TextView tv = view.findViewById(R.id.tv);
}
I have created the demo you can refer it and implement for single selection
recyclerView.setAdapter(new RecyclerView.Adapter() {
int selected_position = -1;
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new RecyclerView.ViewHolder(LayoutInflater.from(parent.getContext()).inflate(
R.layout.row_color_list,parent,false)) {
#Override
public String toString() {
return super.toString();
}
};
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
ImageView imageView = holder.itemView.findViewById(R.id.image);
if(selected_position == position){
imageView.setVisibility(View.VISIBLE);
}else {
imageView.setVisibility(View.GONE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(selected_position != holder.getAdapterPosition()){
selected_position = holder.getAdapterPosition();
notifyDataSetChanged();
}
}
});
}
#Override
public int getItemCount() {
return 20;
}
});
You can do as following:
1) Declare a global variable:
private int selectedPos = -100; // Put any irrelevant number you want
2) Set selected position onClick() :
#Override
public void onClick(View v) {
selectedPos = getAdapterPosition();
}
3) Check selected postion and assign visibility inside onBindViewHolder():
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
if(position == selectedPos){
holder.imageViewCheck.setVisibility(View.VISIBLE);
} else {
holder.imageViewCheck.setVisibility(View.INVISIBLE);
}
}
Try this code..
add this code into adapter class for handling click event..
OnItemClick onItemClick;
public void setOnItemClick(OnItemClick onItemClick) {
this.onItemClick = onItemClick;
}
public interface OnItemClick {
void getPosition(String data); //pass any data to shared it.
}
after bind method..
#Override
public void onBindViewHolder(final ItemViewHolder holder, final int position) {
// below code handle click event on recycler view item.
final String str=mStringList.get(position); // here your boject
if(holder.category.isChecked()==true){
holder.imageViewCheck.setVisibility(View.VISIBLE);
current_pos=position;
} else {
holder.imageViewCheck.setVisibility(View.INVISIBLE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClick.getPosition(str); // pass your data.
}
});
}
after bind adapter into recycler view it means adapter not null then called below code..
adpater.setOnItemClick(new RecyclerViewAdpater.OnItemClick() {
#Override
public void getPosition(String data) {
// hear update your value for check into if condition.
data="sdfsdf";
adpater.notifyDataSetChanged();
}
});
and also read comments and also try to make custon class and access that object value and update after click it..
this code only how to handle click event into recycler view.
My Title is kind of hard to understand but basically when I add items into my database is should display it in a RecyclerView. Now in my RecyclerView I have two layouts but the problem is the first item of my database goes behind my first item in my other layout. So if I have 3 items in my database, it shows only 2 items from the database and the first item hides behind my first item in the RecyclerView which is a different layout that does not use the database at all.
This is my code:
FirebaseRecyclerOptions<Event> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<Event>()
.setQuery(query1, Event.class).build();
AccAdapter = new FirebaseRecyclerAdapter<Event, RecyclerView.ViewHolder>(firebaseRecyclerOptions){
final static int TYPE_HEADER = 0;
final static int TYPE_ITEM = 1;
#Override
public int getItemViewType(int position) {
if (position == 0) return TYPE_HEADER;
return TYPE_ITEM;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HEADER){
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_add_items,
parent, false);
return new ProdudctHolder3(view);
} else {
View view = LayoutInflater.from(getActivity()).inflate(R.layout.recycler_view_row_acc,
parent, false);
return new ProductHolder2(view);
}
}
#Override
protected void onBindViewHolder(final RecyclerView.ViewHolder holder, int position, final Event model) {
if (holder instanceof ProdudctHolder3){
((ProdudctHolder3) holder).addBackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getActivity(), AccAddItems.class ));
}
});
} else{
final ProductHolder2 productHolder2 = (ProductHolder2) holder;
productHolder2.mName.setText(model.getName());
productHolder2.view.setBackgroundResource(getBackgroundDrawable(Integer.valueOf(model.getProductAmount())));
productHolder2.mbackground.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog = new Dialog(getActivity());
dialog.setContentView(R.layout.popup_edit_product);
SeekBar amountSeekBar = dialog.findViewById(R.id.amountSeekBar);
amountSeekBar.setMax(100);
amountSeekBar.setProgress(Integer.valueOf(model.getProductAmount()));
amountSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
progress = i;
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
getRef(holder.getAdapterPosition()).child("productAmount").setValue(String.valueOf(progress));
dialog.dismiss();
}
});
dialog.show();
}
});
productHolder2.mbackground.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
final PopupMenu popupMenu = new PopupMenu(getActivity(), productHolder2.mbackground);
popupMenu.inflate(R.menu.menu_acc);
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem menuItem) {
switch (menuItem.getItemId()){
case R.id.deleteProduct:
getRef(productHolder2.getAdapterPosition()).removeValue();
popupMenu.dismiss();
return true;
default:
return false;
}
}
});
popupMenu.show();
return true;
}
});
}
}
};
mAccRecyclerViewRef.setAdapter(AccAdapter);
My two Product Holders
private class ProdudctHolder3 extends RecyclerView.ViewHolder{
private RelativeLayout addBackground;
public ProdudctHolder3(View itemView) {
super(itemView);
addBackground = itemView.findViewById(R.id.mBackground2);
}
}
private class ProductHolder2 extends RecyclerView.ViewHolder{
private TextView mName;
private RelativeLayout mbackground;
private View view;
public ProductHolder2(View itemView) {
super(itemView);
mName = itemView.findViewById(R.id.ItemName);
mbackground = itemView.findViewById(R.id.mBackground1);
view = itemView.findViewById(R.id.amountIndicator);
}
}
The ideal solution would have been to set two adapters on a single RecyclerView but unfortunatelly this is not possible.
However, you can make a single custom Adapter that handles two types of items. I will explain this by getting an example.
Let's assume you need to display objects of two types, humans and aliens. Your objects require completely different layouts and completely different ViewHolders. Please see the below code for the ViewHolders:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static class HumanViewHolder extends RecyclerView.ViewHolder {
public HumanViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Human human) {
//Display your human object
}
}
private static class AlienViewHolder extends RecyclerView.ViewHolder {
public AlienViewHolder(View itemView) {
super(itemView);
//Prepare your ViewHolder
}
public void bind(Alien alien) {
//Display your alien object
}
}
}
First you need to add two different constants to your adapter representing both type of views:
private static final int ITEM_TYPE_HUMAN;
private static final int ITEM_TYPE_ALIEN;
To keep things simple, let's also assume you store your objects in a list:
private List<Object> items = new ArrayList<>();
public MyAdapter(List<Object> items) {
this.items.addAll(items);
//Other stuff if needed
}
Now, the first you need to do, is to implement getItemViewType() method:
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof Human) {
return ITEM_TYPE_HUMAN;
} else {
return ITEM_TYPE_ALIEN;
}
}
Second, you need to use the item type inside the onCreateViewHolder() method like this:
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
if (viewType == ITEM_TYPE_HUMAN) {
View view = layoutInflater.inflate(R.layout.item_human, parent, false);
return new HumanViewHolder(view);
} else {
View view = layoutInflater.inflate(R.layout.item_alien, parent, false);
return new AlienViewHolder(view);
}
}
In the end, you just need to bind the proper view holder like this:
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
Object item = items.get(position);
if (viewHolder instanceof HumanViewHolder) {
((HumanViewHolder) viewHolder).bind((Human) item);
} else {
((AlienViewHolder) viewHolder).bind((Alien) item);
}
}
Why use the Firebase Recycler Adapter when you could easily make a custom one? If I understood well you want an item to be fixed at position 0 (header) while others will be added below the first one, right? If so, here is a solution I like to use:
public interface ViewType {
public int getViewType();
}
public interface ViewTypeDelegateAdapter {
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent);
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item);
}
public class ViewTypes {
public static int HEADER = 0
public static int ITEM = 1
}
public class ProductDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new ProductHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as ProductHolder).bind("test");
}
class ProductHolder extends RecyclerView.ViewHolder {
public ProductHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class HeaderDelegateAdapter implements ViewTypeDelegateAdapter {
private int resID;
private Context context;
public ProductDelegateAdapter(int resID, Context context) {
this.resID = resID;
this.context = context;
}
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent) {
return new HeaderHolder(LayoutInflater.from(parent.context).inflate(resID, parent, false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, ViewType item) {
(holder as HeaderHolder).bind("test");
}
class HeaderHolder extends RecyclerView.ViewHolder {
public HeaderHolder(View view) {
super(view);
}
public void bind(String test) {
}
}
}
public class AccAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>() {
private Context context;
private List<ViewType> items;
private SparseArrayCompat<ViewTypeDelegateAdapter> delegateAdapters;
private ViewType headerItem;
public AccAdapter(Context context) {
this.context = context;
this.items = new ArrayList();
this.delegateAdapters = new SparseArrayCompat();
this.headerItem = new ViewType() {
#Override
public int getViewType() {
return ViewTypes.HEADER;
}
};
this.items.add(this.headerItem);
this.delegateAdapters.put(ViewTypes.HEADER, HeaderDelegateAdapter(R.id.test, this.context));
this.delegateAdapters.put(ViewTypes.ITEM, ProductDelegateAdapter(R.id.test, this.context));
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, Int viewType) {
return delegateAdapters.get(viewType).onCreateViewHolder(parent);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, Int position) {
delegateAdapters.get(getItemViewType(position)).onBindViewHolder(holder, items[position])
}
#Override
public Int getItemViewType(Int position) {
return items.get(position).getViewType();
}
#Override
public Int getItemCount() {
return items.getSize();
}
public void add(ViewType viewType) {
val initPosition = this.items.size - 1
this.items.add(item)
notifyItemRangeChanged(initPosition, this.items.size + 1)
}
}
public class Event implements ViewType {
private String id;
#Override
public int getViewType() {
return ViewTypes.ITEM;
}
}
Excuse me for some syntax errors, I've translated to Java from Kotlin to help you. Hope it helps!
I have a check box in RecyclerView Adapter's View Item.
When scrolling, some check boxes are getting checked and some are getting unchecked.
I have taken help from this and this
But I am unable to find the exact solution to this.
Here is my code
public class AllContactsAdapter extends RecyclerView.Adapter<AllContactsAdapter.ViewHolder> {
private Context context;
private ArrayList<PhoneContactsModel> listOfContacts = new ArrayList<>();
PhoneContactsModel phoneContactsModel;
private ArrayList<PhoneContactsModel> copyOfListOfContacts = new ArrayList<>();
public AllContactsAdapter(Context context, ArrayList<PhoneContactsModel> listOfContacts) {
this.context = context;
this.listOfContacts = listOfContacts;
// copyOfListOfContacts.addAll(listOfContacts);
}
#Override
public AllContactsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.
adapter_load_allusers_contacts_listitem, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(final AllContactsAdapter.ViewHolder holder, final int position) {
Log.d("tag", "adapter========3");
phoneContactsModel = listOfContacts.get(position);
holder.name.setText(phoneContactsModel.getContactName());
holder.phoneNumber.setText(phoneContactsModel.getContactNumber());
holder.checkBox.setSelected(phoneContactsModel.isChecked());
holder.contactLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (holder.checkBox.isChecked()) {
phoneContactsModel.setChecked(false);
holder.checkBox.setChecked(false);
copyOfListOfContacts.remove(listOfContacts.get(position));
} else {
phoneContactsModel.setChecked(true);
holder.checkBox.setChecked(true);
copyOfListOfContacts.add(listOfContacts.get(position));
}
}
});
}
#Override
public int getItemCount() {
return listOfContacts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView name, phoneNumber;
private CheckBox checkBox;
private LinearLayout contactLayout;
public ViewHolder(View view) {
super(view);
name = view.findViewById(R.id.contactNameId);
phoneNumber = view.findViewById(R.id.contactNumberId);
checkBox = view.findViewById(R.id.checkBoxId);
contactLayout = view.findViewById(R.id.contactLayoutId);
}
}
}
For example, I have checked 1,2,3 items in list. When I scrolled down and come up , then 13 is checked and 2 is unchecked along with other some items.Please help me.
Any solution is appreciated.
A simple way arround is do not use OnCheckedChangeListener just set OnClickListener on Check box . Move checkBox onclick inside ViewHolder class.
public class ViewHolder1 extends RecyclerView.ViewHolder implements View.OnClickListener {
CheckBox checkBox;
public ViewHolder1(View itemView) {
super(itemView);
checkBox = (TextView) itemView.findViewById(R.id.checkBox);
checkBox.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if(getAdapterPosition()!=-1) {
phoneContactsModel.get(getAdapterPosition()).setChecked(!phoneContactsModel.get(getAdapterPosition()).isChecked());
notifyItemChanged(getAdapterPosition());
}
}
}
And
public void onBindViewHolder(final AllContactsAdapter.ViewHolder holder, final int position) {
holder.checkBox.setChecked(phoneContactsModel.isChecked());
}
notify your adapter.
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
phoneContactsModel.setChecked(b);
//notifyItemChanged(position);(if you want to notify change in single item)
//or
//notifyDataSetChanged();(if you want to notify change in all)
}
});
no need to use this line of code twice
holder.checkBox.setSelected(phoneContactsModel.isChecked());
//this section seems buggy i assume you want to add the item to the list when ever the check box is checked and remove it from the list when ever the check box is unchecked.
holder.contactLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (phoneContactsModel.isChecked()) {
holder.checkBox.setSelected(false);
copyOfListOfContacts.remove(listOfContacts.get(position));
} else {
holder.checkBox.setSelected(true);
copyOfListOfContacts.add(listOfContacts.get(position));
}
}
}
);
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final PhoneContactsModel phoneContactsModel = listOfContacts.get(position);
holder.name.setText(phoneContactsModel.getContactName());
holder.phoneNumber.setText(phoneContactsModel.getContactNumber());
holder.checkBox.setChecked(/* gets value from the modal */ phoneContactsModel.isChecked());
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean value) {
if (compoundButton.isPressed()) {
holder.checkBox.setChecked(value);
// set the value into the modal.
phoneContactsModel.setChecked(value);
if (value) {
copyOfListOfContacts.remove(phoneContactsModel);
} else {
copyOfListOfContacts.add(phoneContactsModel);
}
}
}
});
}
Change your onBindViewHolder method like this. There won't be any unnecessary checks.
I have made Navigation Drawer and used recyclerView for checkBoxes in drawer item.
Now I wanted all checkbox which was checked before app is closed to get checked in onCreate of navigation drawer.
Here is my adapter class see :
class NavigationDrawerAdapter extends RecyclerView.Adapter<NavigationDrawerAdapter.MyViewHolder> {
List<NavDrawerItem> data = Collections.emptyList();
private LayoutInflater inflater;
private Context context;
private int selected_position = -1;
private static String sel=null;
NavigationDrawerAdapter(Context context, List<NavDrawerItem> data) {
this.context = context;
inflater = LayoutInflater.from(context);
this.data = data;
}
public void delete(int position) {
data.remove(position);
notifyItemRemoved(position);
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.nav_drawer_row, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
final NavDrawerItem current = data.get(holder.getAdapterPosition());
holder.title.setText(current.getTitle());
holder.title.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public boolean isChecked(){
if(holder.title.isChecked()){
return true;
}
else {
return false;
}
}
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(isChecked()){
sel
}
if (!current.isShowNotify()){
current.setShowNotify(true);
}else {
current.setShowNotify(false);
}
}
});
}
public void setPref(SharedPreferences pref){
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(hasStableIds);
}
#Override
public int getItemCount() {
return data.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
CheckBox title;
MyViewHolder(View itemView) {
super(itemView);
title = (CheckBox) itemView.findViewById(R.id.title);
}
}
}
I guess I have to do something here that's why I posted only this class.
I have FragmentDrawer class too but I think I need to do something here first , I am not able to use sharedpreferences Please help
euse the checked data in array save it in some shared prefrence in gragment drawer , you need to check whether that array is available or not, If available populate the responses in checkboxes
SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor=prefs1.edit();
editor.putString("","");
editor.commit();
// according to your need what you need to store .
prefs1.getString("","");
// now get the stored content with this when you need to populate the data
////////////////////////////////////////////////////////////////////////PUT THIS IN ONCHECKCHANGED //////////////
Fragmentdrawer fd=new FragmentDrawer();
fd.somemethod(position,ischecked,context);
and made a method in fragment drawer use it to get position in fragment drawer