On click of button when I'm scrolling the view, it changes the
position of that clicked button. On every scroll it's showing different
position.
public class ProductAdapter extends
RecyclerView.Adapter<ProductAdapter.ProductViewHolder> {
Context ctx;
ArrayList<ProductDetail> productList;
public ProductAdapter(Context ctx, ArrayList<ProductDetail> productList) {
this.ctx = ctx;
this.productList = productList;
}
#Override
public int getItemCount() {
return productList.size();
}
#Override
public void onBindViewHolder(final ProductViewHolder vHolder, int pos) {
vHolder.txt_prod_name.setText(productList.get(pos).getProduct_desc());
vHolder.btn_add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
vHolder.lyt_prod_qty.setVisibility(View.VISIBLE);
vHolder.btn_add.setVisibility(View.GONE);
}
});
}
#Override
public ProductViewHolder onCreateViewHolder(ViewGroup parent, int arg1) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.activity_recycler_search_item, null);
ProductViewHolder viewHolder = new ProductViewHolder(view);
return viewHolder;
}
public class ProductViewHolder extends RecyclerView.ViewHolder {
TextView txt_prod_name;
TextView txt_delivery_type;
TextView txt_prod_mrp;
Spinner spn_prod_qty;
LinearLayout list_lyt, lyt_prod_qty;
Button btn_add;
public ProductViewHolder(View itemView) {
super(itemView);
txt_prod_name = (TextView) itemView
.findViewById(R.id.txt_prod_name);
txt_delivery_type = (TextView) itemView
.findViewById(R.id.txt_delivery_type);
txt_prod_mrp = (TextView) itemView.findViewById(R.id.txt_prod_mrp);
btn_add = (Button) itemView.findViewById(R.id.btn_add);
lyt_prod_qty = (LinearLayout) itemView
.findViewById(R.id.lyt_prod_qty);
}
}
}
On click of Button when I'mm scrolling the view, it changes the position of that clicked button. On every scroll it's showing different
position. Where should I out my click logic or should refresh the adapter every time?
In your ProductDetail modal class add a member boolean isButtonClicked; and add its getter and setter as well. Then make following changes in your onBindViewHolder method:
#Override
public void onBindViewHolder(final ProductViewHolder vHolder, int pos) {
final ProductDetail productDetail = productList.get(pos);
vHolder.txt_prod_name.setText(productDetail.getProduct_desc());
if(productDetail.isButtonClicked()){
vHolder.lyt_prod_qty.setVisibility(View.VISIBLE);
vHolder.btn_add.setVisibility(View.GONE);
} else {
vHolder.lyt_prod_qty.setVisibility(View.GONE);
vHolder.btn_add.setVisibility(View.VISIBLE);
}
vHolder.btn_add.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
vHolder.lyt_prod_qty.setVisibility(View.VISIBLE);
vHolder.btn_add.setVisibility(View.GONE);
productDetail.setIsButtonClicked(true);
}
});
}
Related
I used android RecyclerView.Adapter. i can not manage my onClickListener.When I do click on item worked and this ithem and another item
When I set my itemView
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setVisibility(View.GONE);
}
});
and when do click 'GONE' works to two items.
see in photo
this my adapter.
public class WordAdapter extends RecyclerView.Adapter<WordAdapter.ViewHolder> {
private List<LessonListActivity.Words> words;
public WordAdapter(List<LessonListActivity.Words> words) {
this.words = words;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View listItem = layoutInflater.inflate(R.layout.adapter_content, parent, false);
ViewHolder viewHolder = new ViewHolder(listItem);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final LessonListActivity.Words myListData = words.get(position);
holder.textView.setText(words.get(position).getEN());
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(hasStableIds);
}
#Override
public int getItemCount() {
return words.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public RelativeLayout relativeLayout;
public ViewHolder(View itemView) {
super(itemView);
this.textView = (TextView) itemView.findViewById(R.id.word);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.relative_layout);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setVisibility(View.GONE);
}
});
}
}
}
what can i do to make them work only if we click them?
You can use one list to save all selected indexes and use it in onBindViewHolder to manage visibility of views.
Add index to be removed in list by clicking on view.
public class WordAdapter extends RecyclerView.Adapter<WordAdapter.ViewHolder> {
private List<LessonListActivity.Words> words;
ArrayList<Integer> listSelected = new ArrayList<>();
public WordAdapter(List<Words> words) {
this.words = words;
}
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
View listItem = layoutInflater.inflate(R.layout.adapter_content, parent, false);
ViewHolder viewHolder = new ViewHolder(listItem);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final LessonListActivity.Words myListData = words.get(position);
holder.textView.setText(words.get(position).getEN());
if (listSelected.contains(position)) {
//Here view will be invisible it will show white space. you can set height 0 to remove white space.
holder.itemView.setVisibility(View.GONE);
} else holder.itemView.setVisibility(View.VISIBLE);
}
#Override
public void setHasStableIds(boolean hasStableIds) {
super.setHasStableIds(hasStableIds);
}
#Override
public int getItemCount() {
return words.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView textView;
public RelativeLayout relativeLayout;
public ViewHolder(View itemView) {
super(itemView);
this.textView = (TextView) itemView.findViewById(R.id.word);
relativeLayout = (RelativeLayout) itemView.findViewById(R.id.relative_layout);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!listSelected.contains(getLayoutPosition())) {
listSelected.add(getLayoutPosition());
}
notifyItemChanged(getLayoutPosition());
}
});
}
}
}
If someone can help me. I've a RecyclerView with items but when i try to select ONE item, i can select many items. I think that the problem is in the onClick callback but i don't know exactly. This is the adapter code:
public class HorizontalRecyclerViewAdapter extends RecyclerView
.Adapter<HorizontalRecyclerViewAdapter
.DataObjectHolder> {
private ArrayList<HorizontalData> mDataset;
private static MyClickListener myClickListener;
private SparseBooleanArray selectedItem = new SparseBooleanArray();
public class DataObjectHolder extends RecyclerView.ViewHolder
implements View
.OnClickListener {
TextView mLabel;
TextView mDateTime;
LinearLayout linearLayout;
public DataObjectHolder(View itemView) {
super(itemView);
mLabel = (TextView) itemView.findViewById(R.id.item_list_view_text_view);
mDateTime = (TextView) itemView.findViewById(R.id.item_list_view_text_view_two);
linearLayout = (LinearLayout) itemView.findViewById(R.id.myBackground);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (selectedItem.get(getAdapterPosition(), false)) {
selectedItem.delete(getAdapterPosition());
v.setSelected(false);
} else {
selectedItem.put(getAdapterPosition(), true);
v.setSelected(true);
}
myClickListener.onItemClick(getAdapterPosition(), v);
}
}
public void setOnItemClickListener(MyClickListener myClickListener) {
this.myClickListener = myClickListener;
}
public HorizontalRecyclerViewAdapter(ArrayList<HorizontalData> myDataset) {
mDataset = myDataset;
}
#Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.date_item, parent, false);
DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
return dataObjectHolder;
}
#Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
holder.linearLayout.setSelected(selectedItem.get(position, false));
holder.mLabel.setText(mDataset.get(position).getmTitle());
holder.mDateTime.setText(mDataset.get(position).getmSubTitle());
}
#Override
public int getItemCount() {
return mDataset.size();
}
public interface MyClickListener {
void onItemClick(int position, View v);
}
}
Thanks!
First of all you don't need SparseBooleanArray, because you want only one item to be selected. It'd be enough to have int selectedItemPos with would represent currently selected item position.
Here's a simple adapter that I've just created and it's working, with comments explaining what's happening:
public class TestAdapter extends RecyclerView.Adapter<TestAdapter.ViewHolder> {
private ArrayList<String> items;
//field mentioned before
private int selectedItemPos = -1;
//I create some items to see if my adapter is working.
public TestAdapter() {
this.items = new ArrayList<>();
for (int i=0; i<20; i++) {
items.add("Test" + i);
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false));
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
String item = items.get(position);
holder.mName.setText(item);
//This line sets selection state to true if current position is the same as selected one, and false otherwise.
holder.itemView.setSelected(selectedItemPos == position);
}
#Override
public int getItemCount() {
return items.size();
}
//helper method
protected void setSelectedItem(int position) {
int oldSelected = selectedItemPos;
selectedItemPos = position;
// update view of unselected item
notifyItemChanged(oldSelected);
//update view of just selected item
notifyItemChanged(selectedItemPos);
}
protected class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView mName;
public ViewHolder(View view) {
super(view);
mName = (TextView) view.findViewById(R.id.taskListItem_name);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
//if the clicked item is already selected,
// we will just unselect it and no new item will be selected
//(new one is -1, which is none)
int newSelectedItem = getAdapterPosition()==selectedItemPos?-1:getAdapterPosition();
//apply changes on adapter
setSelectedItem(newSelectedItem);
}
}
}
You should be able to easily merge this code with yours.
i have recycler view and i highlight the item when i click in it , the problem is i can highlight many item , i wont just one item , when i click into item is highlight and when i click another item is highlight too
this is MyAdapter
public class ScreenRecyclerAdapter extends RecyclerView.Adapter<ScreenRecyclerAdapter.ViewHolder> {
Context context;
int image_list[];
ImageView image_view_screen_item;
public ScreenRecyclerAdapter(int[] image_list, Context context){
super();
this.image_list = image_list;
this.context = context;}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.screen_items, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Picasso.with(context).load(image_list[position]).into(holder.image_view_screen_item);
holder.list_row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
#Override
public int getItemCount() {
return image_list.length;
}
class ViewHolder extends RecyclerView.ViewHolder{
ImageView image_view_screen_item , back;
RelativeLayout list_row;
public ViewHolder(View itemView) {
super(itemView);
image_view_screen_item = (ImageView) itemView.findViewById(R.id.plantImageView);
list_row = (RelativeLayout) itemView.findViewById(R.id.list_row);
list_row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
list_row.setBackgroundColor(Color.parseColor("#d5d5d5"));
Intent i = new Intent(context, ImagePager.class);
context.startActivity(i);
}
});
}}}
First define a list of RelativeLayouts for your adapter which contains every rows:
List<RelativeLayout> items;
Then in your onBindViewHolder method, add:
items.add(holder.list_row);
Now add a method to your adapter like this:
private void makeAllWhite() {
for(RelativeLayout item : items) {
item.setBackgroundColor(Color.parseColor("#ffffff"));
}
}
Finally before this line:
list_row.setBackgroundColor(Color.parseColor("#d5d5d5"));
call:
makeAllWhite();
Your final code should be like this:
public class ScreenRecyclerAdapter extends RecyclerView.Adapter<ScreenRecyclerAdapter.ViewHolder> {
Context context;
int image_list[];
ImageView image_view_screen_item;
List<RelativeLayout> items;
public ScreenRecyclerAdapter(int[] image_list, Context context){
super();
this.image_list = image_list;
this.context = context;
this.items = new ArrayList<>();
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.screen_items, parent, false);
ViewHolder viewHolder = new ViewHolder(v);
return viewHolder;}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
items.add(holder.list_row);
Picasso.with(context).load(image_list[position]).into(holder.image_view_screen_item);
}
#Override
public int getItemCount() {
return image_list.length;
}
class ViewHolder extends RecyclerView.ViewHolder{
ImageView image_view_screen_item , back;
RelativeLayout list_row;
public ViewHolder(View itemView) {
super(itemView);
image_view_screen_item = (ImageView) itemView.findViewById(R.id.plantImageView);
list_row = (RelativeLayout) itemView.findViewById(R.id.list_row);
list_row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
makeAllWhite();
list_row.setBackgroundColor(Color.parseColor("#d5d5d5"));
Intent i = new Intent(context, ImagePager.class);
context.startActivity(i);
}
});
}
}
private void makeAllWhite() {
for(RelativeLayout item : items) {
item.setBackgroundColor(Color.parseColor("#ffffff")));
}
}
}
I have done the same thing here. There are multiple solutions to it but what I found most convenient is storing a copy of the view (or viewholder, both work) and in every onClick event check if the view (or viewholder) is same, if not then change the background of the previously selected view and set the new background for the selected item else use return ;
In your adapter, you're setting the OnClickListener for the ViewHolder, which is basically representing every item. The binding (of data, design, events, etc.) is happening in onBindViewHolder according to the position in the dataset. So just move your event implementation from the constructor of ViewHolder to onBindViewHolder.
It may be irrelevant because it seems that your dataset isn't modified by the event, but if it does, don't forget to call notifyDataSetChanged() after modification.
In RecyclerView.Adapter i need to change favIcon in each row list that after select each position just specified row favIcon change.
All thing is right but when scroll RecyclerView , position of selected row change automatically!
it's my adapter class :
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ItemData[] itemsData;
Activity activity;
public MyAdapter(Activity activity, ItemData[] itemsData) {
this.activity=activity;
this.itemsData = itemsData;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout, null);
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
viewHolder.txtViewTitle.setText(itemsData[position].getTitle());
viewHolder.imgViewIcon.setImageResource(itemsData[position].getImageUrl());
viewHolder.imgViewIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!viewHolder.isFav) {
Toast.makeText(activity,"Selected Row : "+position,Toast.LENGTH_SHORT).show();
viewHolder.isFav = true;
viewHolder.imgViewIcon.setImageResource(R.drawable.icon_fav);
} else {
viewHolder.imgViewIcon.setImageResource(R.drawable.pre_ic_ab_drawer);
viewHolder.isFav = false;
}
}
});
if (viewHolder.isFav)
viewHolder.imgViewIcon.setImageResource(R.drawable.icon_fav);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtViewTitle;
public ImageView imgViewIcon;
public Boolean isFav=false;
public ViewHolder(View itemLayoutView) {
super(itemLayoutView);
txtViewTitle = (TextView) itemLayoutView.findViewById(R.id.item_title);
imgViewIcon = (ImageView) itemLayoutView.findViewById(R.id.item_icon);
}
}
#Override
public int getItemCount() {
return itemsData.length;
}
}
What I see in the output :
As seen i select first row icon , but after scroll RecyclerView , selected position change.
Then try to use changing favIconand imgViewIcon.setOnClickListener in onCreateViewHolder again wrong position!
Too i try to store position in sharedPreferences or modelClass , but this return wrong position in scrolling yet
There is a way to avoid this problem?
I saw this solution Too :Get clicked item and its position in RecyclerView
Try to use your model ItemData[] itemsData; to save if element is selected.
eg.
if (itemsData[position].isFav){
viewHolder.imgViewIcon.setImageResource(R.drawable.icon_fav);
}else{
viewHolder.imgViewIcon.setImageResource(R.drawable.pre_ic_ab_drawer);
}
viewHolder.imgViewIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!itemsData[position].isFav) {
Toast.makeText(activity,"Selected Row : "+position,Toast.LENGTH_SHORT).show();
itemsData[position].isFav = true;
viewHolder.imgViewIcon.setImageResource(R.drawable.icon_fav);
} else {
viewHolder.imgViewIcon.setImageResource(R.drawable.pre_ic_ab_drawer);
itemsData[position].isFav = false;
}
}
});
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ItemData[] itemsData;
Activity activity;
public MyAdapter(Activity activity, ItemData[] itemsData) {
this.activity=activity;
this.itemsData = itemsData;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View itemLayoutView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout, null);
ViewHolder viewHolder = new ViewHolder(itemLayoutView);
return viewHolder;
}
#Override
public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
viewHolder.txtViewTitle.setText(itemsData[position].getTitle());
viewHolder.imgViewIcon.setImageResource(itemsData[position].getImageUrl());
viewHolder.imgViewIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (!viewHolder.isFav) {
Toast.makeText(activity,"Selected Row : "+position,Toast.LENGTH_SHORT).show();
viewHolder.isFav = true;
viewHolder.imgViewIcon.setImageResource(R.drawable.icon_fav);
} else {
viewHolder.imgViewIcon.setImageResource(R.drawable.pre_ic_ab_drawer);
viewHolder.isFav = false;
}
}
});
if (viewHolder.isFav)
viewHolder.imgViewIcon.setImageResource(R.drawable.icon_fav);
else
// The change
viewHolder.imgViewIcon.setImageResource(R.drawable.pre_ic_ab_drawer);
}
When you bind the ViewHolder you should reset the ImageView icon if it's not fav.
I wrote a code about changing the TextView background after clicking the text, however the background color did not change but the other TextView background color change. I understand recyclerview is to reuse the view, so i set notifyItemchanged() to avoid it to reset the view.
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{
private List<String> innertext;
private Context mContext;
public MyAdapter(List<String> items,Context context){
this.innertext = items;
this.mContext = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.background_color, parent, false);
MyViewHolder holder = new MyViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
String s = innertext.get(position);
holder.t1.setText(s);
}
#Override
public int getItemCount() {
return innertext.size();
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public TextView t1;
public MyViewHolder(View itemView) {
super(itemView);
t1 = (TextView)itemView.findViewById(R.id.t1);
t1.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
t1.setBackgroundColor(Color.parseColor("#455A64"));
notifyItemChanged(pos);
}
}
}
if you need more code from me please let me know.
This is not a tried code but it will explain the logic to you:-
public class MyAdapter extends RecyclerView.Adapter {
private List<String> innertext;
private Context mContext;
private boolean[] checked={false};
public MyAdapter(List<String> items, Context context) {
this.innertext = items;
this.mContext = context;
checked = new boolean[items.size()];
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.background_color, parent, false);
MyViewHolder holder = new MyViewHolder(v);
return holder;
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
String s = innertext.get(position);
((MyViewHolder)holder).t1.setText(s);
if(checked[position]){
((MyViewHolder)holder).t1.setBackgroundColor(Color.parseColor("#455A64"));
}
}
#Override
public int getItemCount() {
return innertext.size();
}
class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView t1;
public MyViewHolder(View itemView) {
super(itemView);
t1 = (TextView) itemView.findViewById(R.id.t1);
t1.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
checked[pos] = true;
notifyItemChanged(pos);
}
}
}
basically you have to store the position which has been clicked in a boolean array and then set color in onbindview by checking if it has been clicked, as recyclerview doesnt work the way u think, it recycle Views
Try this:
t1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
t1.setBackgroundColor(Color.parseColor("#455A64"));
}
});
Hope it helps.
This may help you
copy & paste below code in method onBindViewHolder
holder.t1.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
t1.setBackgroundColor(ContextCompat.getColor(mContext, Color.parseColor("#455A64")););
}
});
+1 to #ankitagrawal. I think that's the correct solution!
This is my answer.
- The same logic but different approach. Hope i did this right because i'm not using AS or eclipse. I just modified #ankitagrawal's answer. Thanks :)
http://pastebin.com/C7fqhhUa