setOnClickListener changes every seventh view in recyclerview - android-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"));
}

Related

highlight items in recyclerview android

I am trying to select items in recylerview. When I click an item, a checkbox appears on that item and it is highlighted. But the problem is that when I scroll, the item which is highlighted goes to its original color but the checkbox image remains as it should. Why the highlighted color is gone but the image remains after scrolling, I want the items to keep their state after scrolling.
public static List<Model> item = new ArrayList<Model>()
#Override
public void onBindViewHolder(#NonNull MyAdapter.MyViewHolder holder, int
position) {
holder.bind(item.get(position));
//
public class MyViewHolder extends RecyclerView.ViewHolder{
public MyViewHolder(#NonNull View itemView) {
super(itemView);
imageView = itemView.findViewById(R.id.check);
public void bind(Model model) {
if (model.isChecked()){
imageView.setVisibility(View.VISIBLE);
itemView.setBackgroundColor(Color.GRAY);
model.setChecked(true);
} else {
imageView.setVisibility(View.GONE);
itemView.setBackgroundColor(Color.TRANSPARENT);
model.setChecked(false);
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Model s = item.get(getAdapterPosition());
if (!selectList.contains(s)){
selectList.add(s);
model.setChecked(true);
} else {
selectList.remove(s);
model.setChecked(false);
}
notifyItemChanged(getAdapterPosition());
}
});
public class Model {
private boolean isChecked = false;
public boolean isChecked() {
return isChecked;
}
public void setChecked(boolean checked) {
isChecked = checked;
}
}
Don't manually change the design in the onclick listener, just update your model (as you are already doing: model.setchecked(...) depending on state)
Then call Adapter.notifyItemChanged(getAdapterPosition())
This will force the adapter to reload the item, calling onBindViewHolder, where the design should be updated properly
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Model s = item.get(getAdapterPosition());
if (!selectList.contains(s)){
selectList.add(s);
model.setChecked(true);
} else {
selectList.remove(s);
model.setChecked(false);
}
adapter.notifyItemChanged(getAdapterPosition())
}
In the above example, replace "adapter" with a reference to your recylerview adapter

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);
}
}
}

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);
}
}

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.

RecycleView , some items' subView doesn't show correctly

in fragment
mAdapter = new MessageAdapter(this);
mRV.setLayoutManager(new LinearLayoutManager(getActivity(),LinearLayoutManager.VERTICAL,false));
mRV.setItemAnimator(new DefaultItemAnimator());
DividerItemDecoration itemDecoration = new DividerItemDecoration.Builder()
.setOffsetLeft(ScreenUtil.dip2px(getActivity(), 60 + 10) + this.getResources().getDimensionPixelOffset(R.dimen.horizontal_margin))
.build(getActivity());
mRV.addItemDecoration(itemDecoration);
mRV.setItemViewCacheSize(15);
mRV.setAdapter(mAdapter);
in adapter
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MessageItemHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.w_message_item,parent,false));
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((RVItemInterface)holder).setAdapter(this);
((RVItemInterface)holder).update(dataList.get(position),position);
}
in holder
public class MessageItemHolder extends RecyclerView.ViewHolder implements RVItemInterface{
private RoundAvatar mAvatar;
private TextView mTitle;
private TextView mContent;
private TextView mTime;
private BaseRVAdapter mAdapter;
private MsgDecorVo mMsgDecorVo;
...
#Override
public void update(Object obj, final int position) {
reset();
mMsgDecorVo = (MsgDecorVo) obj;
if(mMsgDecorVo.type == MsgDecorVo.TYPE_CATEGORY){
updateCategory();
MsgVo msgVo = mMsgDecorVo.msgVo;
if(msgVo.getMsg() == null || msgVo.getMsg().equals("")){
mContent.setVisibility(View.GONE);
}else {
mContent.setVisibility(View.VISIBLE);
mContent.setText(msgVo.getMsg());
}
if(msgVo.getTime() == 0){
mTime.setVisibility(View.GONE);
}else {
mTime.setVisibility(View.VISIBLE);
mTime.setText(TimeUtil.transformLong2DateString(msgVo.getTime()));
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
dealCategoryClick();
}
});
}else if(mMsgDecorVo.type == MsgDecorVo.TYPE_CONVERSATION){
...
mContent.setText(ImUtil.getMsgContent(message));
mTime.setText(TimeUtil.transformLong2DateString(message.getMsgTime()));
if(chatUserVo != null){
..
}else {
..
}
}
}
//
private void updateCategory(){
...
}
//
private void dealCategoryClick(){
...
}
#Override
public void setAdapter(RecyclerView.Adapter adapter) {
mAdapter = (BaseRVAdapter) adapter;
}
#Override
public void reset() {
mAvatar.setOnClickListener(null);
mAvatar.setAvatar(R.drawable.avatar_default_circle);
mAvatar.hideTagBottom();
mAvatar.hideTagTop();
}
}
these code in holder
mContent.setText(ImUtil.getMsgContent(message));
mTime.setText(TimeUtil.transformLong2DateString(message.getMsgTime()));
has run
but when I scrolled,some of items doesn't show correctly ,the time and content was gone!
if I notify the recyclerview ,it goes right, and if i scroll again,it will still be wrong
just like the image,you can see some items' (time & content) was gone!
http://g.picphotos.baidu.com/album/s%3D900%3Bq%3D90/sign=297cc7510946f21fcd345253c61f1a5d/a686c9177f3e6709378bcc5538c79f3df9dc5595.jpg "tooltip"
Well, you don't have the full code but I assume it is happening because you are not resetting your view states properly.
For Instance, in your updateCode, if type = TYPE_CATEGORY, you set the mTime's visibility depending on whether getTime is 0 or not. But as you scroll, that row might be re-used for
TYPE_CONVERSATION in which case, mTime's visibility will NOT be updated.