Multiple viewholder in recyclerview - android-recyclerview

I have two completely different layouts. One with image view, the other with text view. I want to be able to use both layout in a recyclerview. How do I go about it please. Help

Yoou have to override the getItemViewType function of the RecyclerAdapter. From that you return an Integer which you capture inside the onCreateViewHolder. Inside there you choose which ViewHolder you inflate.
#Override
public int getItemViewType(int position) {
if (TextUtils.isEmpty(employees.get(position).getEmail())) {
return TYPE_CALL;
} else {
return TYPE_EMAIL;
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view;
if (viewType == TYPE_CALL) { // for call layout
view = LayoutInflater.from(context).inflate(R.layout.item_call, viewGroup, false);
return new CallViewHolder(view);
} else { // for email layout
view = LayoutInflater.from(context).inflate(R.layout.item_email, viewGroup, false);
return new EmailViewHolder(view);
}
}

Related

Highlighted Items in reyclerview lose their state when scolling

I am trying to highlight clicked items in recylerview but as soon as when you scroll the highlighted items do not stay highlighted anymore. I do not know how to keep their state when scrolling. The implementation in the adapter class and given below:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder>{
boolean isEnable = false;
List<ItemFiles> selectList = new ArrayList<>();
public MyAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
view = LayoutInflater.from(parent.getContext()).inflate(R.layout._main,parent,false);
return new MyViewHolder(view);
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder holder, int
position) {
holder.item.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (isEnabled) {
ClickItem(holder);
}
}
private void ClickItem(MyHolder holder) {
ItemFiles s = files.get(holder.getAdapterPosition());
if (holder.highlightItem.getVisibility() == View.GONE){
holder.highlightItem.setVisibility(View.VISIBLE);
holder.highlightItem.setBackgroundColor(Color.LTGRAY);
selectList.add(s);
// this is what I tried to keep the highlighted state but no result
selectList.get(holder.getAdapterPosition()).setSelected(true);
} else {
holder.highlightItem.setVisibility(View.GONE);
holder.highlightItem.setBackgroundColor(Color.TRANSPARENT);
selectList.remove(s);
selectList.get(holder.getAdapterPosition()).setSelected(false);
}
}
}

change background of all textviews in recyclerview from activity and not from adapter

I have a recyclerview with a textview and the clicked textview gets a background around it.I also have a button within the activity which should put a background to all the items in the recyclerview ie..to show all selected.I am putting my activity and adapter code.please help me
my activity code
set_all_days.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CommonUtility.selectedDays.clear();
CommonUtility.selectedDays.addAll(daysList);
//loadDays();
}
});
my adapter
public class DaysAdapter<T> extends RecyclerView.Adapter<DaysAdapter.ViewHolder> {
private ArrayList<String> list=new ArrayList<>();
private Context mContext;
private RecyclerViewClickListener mListener;
public DaysAdapter(ArrayList<String> data, Context context, RecyclerViewClickListener listener) {
list = data;
//languageListFiltered = filteredData;
mContext = context;
mListener = listener;
}
#Override
public void onBindViewHolder(DaysAdapter.ViewHolder viewHolder, final int position) {
viewHolder.titleTextView.setText(list.get(position));
// viewHolder.lang_radio.setChecked(position == mSelectedItem);
}
#Override
public int getItemCount() {
return list.size();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
LayoutInflater inflater = LayoutInflater.from(mContext);
final View view = inflater.inflate(R.layout.days_list_item, viewGroup, false);
return new ViewHolder(view);
}
class ViewHolder extends RecyclerView.ViewHolder {
public TextView titleTextView;
public ViewHolder(final View inflate) {
super(inflate);
titleTextView = (TextView)inflate.findViewById(R.id.text_day);
View.OnClickListener clickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!CommonUtility.selectedDays.contains(titleTextView.getText().toString()))
{
titleTextView.setBackground(mContext.getResources().getDrawable(R.drawable.green_circle));
titleTextView.setTextColor(mContext.getResources().getColor(R.color.white));
CommonUtility.selectedDays.add(titleTextView.getText().toString());
Log.d("added",titleTextView.getText().toString());
}
else
{
int index=CommonUtility.selectedDays.indexOf(titleTextView.getText().toString());
CommonUtility.selectedDays.remove(index);
titleTextView.setBackground(null);
Log.d("removed",titleTextView.getText().toString());
titleTextView.setTextColor(mContext.getResources().getColor(R.color.black));
}
}
};
itemView.setOnClickListener(clickListener);
titleTextView.setOnClickListener(clickListener);
}
}
}

Spinner in RecyclerView to update item values

How can I update the values in my Dataset from a Spinner selection in a RecyclerView? Should I be using LiveData and Room with notifyItemChange(), data binding, or something simpler? I have a Horseclass and a HorseData class. The number of items is static and the options for the variables are static. I do not need to add values or items, I just need to be able to select the variable WinPercentHorse for each item and have that value saved back to the dataset.
public class HorseAdapter extends RecyclerView.Adapter<HorseViewHolder> {
private AdapterView.OnItemSelectedListener onItemSelectedListener;
//we are storing all the horses in a list
private List<Horse> horseList;
//this context we will use to inflate the layout
private Context mCtx;
//getting the context and product list with constructor
public HorseAdapter(Context mCtx, List<Horse> horseList) {
this.mCtx = mCtx;
this.horseList = horseList;
}
#Override
public HorseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//inflating and returning our view holder
LayoutInflater inflater = LayoutInflater.from(mCtx);
View view = inflater.inflate(R.layout.item_layout, null);
return new HorseViewHolder(view);
}
#Override
public void onBindViewHolder(final HorseViewHolder holder, final int position) {
//getting the product of the specified position
Horse horse = horseList.get(position);
//binding the data with the viewholder views
holder.ViewWinPercent.setText(String.valueOf(horse.getWinPercentHorse()));
holder.imageView.setImageDrawable(mCtx.getResources().getDrawable(horse.getImgHorse()));
holder.ViewValueLine.setText(String.valueOf(horse.getValueOdds()));
holder.itemView.setTag(horse.getId());
holder.spinnerView.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
// Update winPercent of item On selecting a spinner item
Toast.makeText(mCtx, "Spinner Selection =" + l + "item selected =" + position, Toast.LENGTH_SHORT).show();
//How to update the WinPercentHorse variable for this item in the horseList
//Then refresh the item notifyItemChange(position, object payload)?
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
}
#Override
public int getItemCount() {
return horseList.size();
}
public void setHorseList(List<Horse> horseList) {
this.horseList = horseList;
notifyDataSetChanged();
}
}
class HorseViewHolder extends RecyclerView.ViewHolder {
TextView ViewWinPercent, ViewValueLine;
ImageView imageView;
Spinner spinnerView;
public HorseViewHolder(View itemView) {
super(itemView);
ViewWinPercent = itemView.findViewById(R.id.winPercentHorse);
ViewValueLine = itemView.findViewById(R.id.valueLine);
imageView = itemView.findViewById(R.id.imgHorse);
spinnerView=itemView.findViewById(R.id.spinner);
}
}

setOnClickListener changes every seventh view in recyclerview

when i click an item in Recyclerview every seventh item gets the effect.
onBindViewHolder:
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.channelName.setText(list.get(position).getChannnelName());
holder.linearLayoutChannelName.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setBackgroundColor(Color.parseColor("#93bcff"));
}
});
}
public class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout linearLayoutChannelName;
TextView channelName;
public ViewHolder(View itemView) {
super(itemView);
channelName = itemView.findViewById(R.id.tv_channel_name);
linearLayoutChannelName = itemView.findViewById(R.id.ll_channelname);
}
}
when i click an item every seventh item changes its backgroung color,and it repeats every seventh item in the list, and even when scrolling across the list the background color dissapears.
https://i.stack.imgur.com/oq2sb.jpg
https://i.stack.imgur.com/rOzQg.jpg
Don't use onClickListener in onBindViewHolder instead set it in onCreateViewHolder and create a member variable to set the selected item. You can do it like this.
int mSelectedItemPosition = -1;
// in your createViewHolder method
holder.linearLayoutChannelName.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
int position = holder.getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
mSelectedItemPosition = position;
notifyItemRangeChanged(0, yourList.size());
}
}
});
And in your bind view holder check selected item position and set the background color
if(mSelectedItemPosition == position){
view.setBackgroundColor(Color.parseColor("#yourColor"))
}else{
view.setBackgroundColor(Color.parseColor("originalColor"));
}

how to set on click listener of recyclerview where list items are heterogenous

I have a recyclerview with 2 types of viewholders for showing 2 types of items
i want to implement on click listener on sub itmes in the items
existing solutions shows viewholder class should be implemented as static inside the adapter ,but i have declared them in sepearte file(a tutorial suggested),
So i cant implement onlick listener on the viewholders
my viewholder1 class is
public class ViewHolder1 extends RecyclerView.ViewHolder {
private TextView label1, label2;
public ImageView postImage;
public ViewHolder1(View v) {
super(v);
label1 = (TextView) v.findViewById(R.id.text11);
label2 = (TextView) v.findViewById(R.id.text22);
postImage = (ImageView) v.findViewById(R.id.dummyImage);
}
public TextView getLabel1() {
return label1;
}
public void setLabel1(TextView label1) {
this.label1 = label1;
}
public TextView getLabel2() {
return label2;
}
public void setLabel2(TextView label2) {
this.label2 = label2;
}
}
viewholder2 is
public class ViewHolder2 extends RecyclerView.ViewHolder {
private ImageView ivExample;
public ViewHolder2(View v) {
super(v);
ivExample = (ImageView) v.findViewById(R.id.ivExample);
}
public ImageView getImageView() {
return ivExample;
}
public void setImageView(ImageView ivExample) {
this.ivExample = ivExample;
}
}
adapter is
public class ComplexRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
// The items to display in your RecyclerView
private List<Object> items;
private final int USER = 0, IMAGE = 1;
// Provide a suitable constructor (depends on the kind of dataset)
public ComplexRecyclerViewAdapter(List<Object> items) {
this.items = items;
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return this.items.size();
}
#Override
public int getItemViewType(int position) {
if (items.get(position) instanceof User) {
return USER;
} else if (items.get(position) instanceof String) {
return IMAGE;
}
return -1;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType) {
case USER:
View v1 = inflater.inflate(R.layout.layout_viewholder1, viewGroup, false);
viewHolder = new ViewHolder1(v1);
break;
case IMAGE:
View v2 = inflater.inflate(R.layout.layout_viewholder2, viewGroup, false);
viewHolder = new ViewHolder2(v2);
break;
default:
View v3 = inflater.inflate(R.layout.layout_viewholder2, viewGroup, false);
viewHolder = new ViewHolder2(v3);
break;
}
return viewHolder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, final int position) {
switch (viewHolder.getItemViewType()) {
case USER:
ViewHolder1 vh1 = (ViewHolder1) viewHolder;
configureViewHolder1(vh1, position);
break;
case IMAGE:
ViewHolder2 vh2 = (ViewHolder2) viewHolder;
configureViewHolder2(vh2);
break;
default:
ViewHolder2 vh3 = (ViewHolder2) viewHolder;
configureViewHolder2(vh3);
break;
}
}
// private void configureDefaultViewHolder(RecyclerViewSimpleTextViewHolder vh, int position) {
// vh.getLabel().setText((CharSequence) items.get(position));
// }
private void configureViewHolder1(ViewHolder1 vh1, int position) {
User user = (User) items.get(position);
if (user != null) {
vh1.getLabel1().setText(user.getMFName());
vh1.getLabel2().setText( user.getMName());
//vh1.postImage.setImageResource(R.drawable.universe);
Picasso.with(vh1.postImage.getContext())
.load(R.drawable.universe)
.resize(400,200) // resizes the image to these dimensions (in pixel)
.centerCrop()
.placeholder(R.drawable.progress_animation)
.error(R.drawable.error_image)
.into(vh1.postImage);
}
}
private void configureViewHolder2(ViewHolder2 vh2) {
// vh2.getImageView().setImageResource(R.drawable.sample_golden_gate);
Picasso.with(vh2.getImageView().getContext())
.load(R.drawable.sample_golden_gate)
.resize(400,200) // resizes the image to these dimensions (in pixel)
.centerCrop()
.placeholder(R.drawable.progress_animation)
.error(R.drawable.error_image)
.into(vh2.getImageView());
}
}
fragment that uses all
public class OneFragment extends Fragment {
private static final int VERTICAL_ITEM_SPACE = 48;
Button button;
RecyclerView rvMixed;
public OneFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_one, container, false);
// Lookup the recyclerview in activity layout
rvMixed = (RecyclerView) rootView.findViewById(R.id.rvContacts);
rvMixed.setAdapter(new ComplexRecyclerViewAdapter(getSampleArrayList()));
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
// Control orientation of the items
// also supports LinearLayoutManager.HORIZONTAL
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// Optionally customize the position you want to default scroll to
layoutManager.scrollToPosition(0);
// Attach layout manager to the RecyclerView
rvMixed.setLayoutManager(layoutManager);
//adding spacing between recycler view items
// rvMixed.addItemDecoration(new VerticalSpaceItemDecoration(VERTICAL_ITEM_SPACE));
// That's all!
return rootView;
}
private void bindDataToAdapter() {
// Bind adapter to recycler view object
rvMixed = (RecyclerView) getView().findViewById(R.id.rvContacts);
ComplexRecyclerViewAdapter mAdapter = new ComplexRecyclerViewAdapter(getSampleArrayList());
rvMixed.setAdapter(mAdapter);
}
private ArrayList<Object> getSampleArrayList() {
ArrayList<Object> items = new ArrayList<>();
items.add(new User("Dany Targaryen", "Valyria"));
items.add(new User("Rob Stark", "Winterfell"));
items.add("image");
items.add(new User("Jon Snow", "Castle Black"));
items.add("image");
items.add(new User("Tyrion Lanister", "King's Landing"));
return items;
}
}
you can simply pass the click Listener on ComplexRecyclerViewAdapter through its constructor at the time of its initialization. And then you can reuse the same click listener reference for each of the ViewHolder.