I am implementing interface to detect when view is clicked in recycler view. I am removing the item when button is clicked. It works fine when once button is clicked. But when I click second time it removes the view present next to it.
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
optionsClickEvent.onDeleteClicked(position, imagePath);
showToast(String.valueOf(position));
}
});
}
Above code is executing in onBind. Next I am removing:
#Override
public void onDeleteClicked(int position, ArrayList<String> filePath) {
filePath.remove(position);
imageAdapter.notifyItemRemoved(position);
}
This works one time perfect. But items are not updated. And when I click delete button second time the item is removed at position+1.
User holder.getAdapterPosition() instead of layout position in onClick
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
optionsClickEvent.onDeleteClicked(holder.getAdapterPosition(), imagePath);
showToast(String.valueOf(position));
}
});
}
Related
This is my code for deletion
public void onBindViewHolder(#NonNull final favAdapter.ViewHolder holder, int position) {
holder.favText.setText(favlist.get(position).getPoetry());
holder.delbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DataBaseHandler db= Room.databaseBuilder(holder.delbtn.getContext(),
DataBaseHandler.class, "room_db").allowMainThreadQueries().build();
Dao_Class userDao= db.userDao();
userDao.delete(favlist.get(position));
favlist.remove(position);
notifyItemRemoved(position);
}
});
}
I tried to get adapter position but I can not get.
Instead of using position, you have to use holder.getAdapterPosition() to handle user clicks.
The ViewHolder provide us the getAdapterPosition which is always have the updated adapter’s position of this holder. It means that whenever you clicked on an item (ViewHolder item) we ask the adapter about it’s position. so you will get the latest position of this item in terms of Adapter’s logic.
You have to remove item position and notify list by applying rangeChanged method
public void onBindViewHolder(#NonNull final favAdapter.ViewHolder holder, int position) {
holder.favText.setText(favlist.get(position).getPoetry());
holder.delbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
DataBaseHandler db= Room.databaseBuilder(holder.delbtn.getContext(),
DataBaseHandler.class, "room_db").allowMainThreadQueries().build();
Dao_Class userDao= db.userDao();
userDao.delete(favlist.get(position));
favlist.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, favlist.size());
}
});
}
I have an item list which are placed under a RecyclerView. On any item, there a quantity(add or subtract). When add is selected, the quantity should increase one.
But when i clicked on '+' for the first time, the value of quantity is setting to 1 and soon after resetting to 0, but when i click on second time the value is becoming '1'. Similarly when i click on next time the value is setting to 2 and after a fraction of second it is still getting to 1 and i click on another time the value is becoming 2. Why by first click is not getting recognized? Can someone please help me here?
public class ItemListAdapter extends RecyclerView.Adapter<ItemListAdapter.ItemViewHolder>{
private Context mContext;
private List<Items> itemsList;
private OnItemListListner onClick;
public ItemListAdapter(Context mContext,List<Items> itemsList)
{
this.mContext=mContext;
this.itemsList=itemsList;
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater=LayoutInflater.from(mContext);
View view=inflater.inflate(R.layout.item_details_layout,null);
return new ItemListAdapter.ItemViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ItemViewHolder holder, final int position) {
Items items=itemsList.get(position);
Log.d("onBindViewHolder",items.getItemName());
holder.itemNameTV.setText(items.getItemName());
String strItemPrice=mContext.getResources().getString(R.string.Rs)+" "+String.valueOf(items.getItemPrice());
holder.itemPriceTV.setText(strItemPrice);
holder.itemDescTV.setText(items.getItemDescription());
Glide.with(mContext).load(items.getItemImagePath()).into(holder.imageView);
holder.itemAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int intCurrentQuantity=Integer.valueOf(holder.itemQuantity.getText().toString());
intCurrentQuantity+=1;
Log.d("myQuantity",String.valueOf(intCurrentQuantity));
holder.itemQuantity.setText(String.valueOf(intCurrentQuantity));
notifyItemChanged(holder.getAdapterPosition());
}
});
holder.itemNameTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onClick.onItemListClick(position);
}
});
holder.itemPriceTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onClick.onItemListClick(position);
}
});
holder.itemDescTV.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onClick.onItemListClick(position);
}
});
holder.imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onClick.onItemListClick(position);
}
});
}
#Override
public int getItemCount() {
return itemsList.size();
}
public void SetOnClick(OnItemListListner onClick)
{
this.onClick=onClick;
}
class ItemViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView itemNameTV,itemPriceTV,itemDescTV,itemQuantity,itemSubtract,itemAdd;
public ItemViewHolder(#NonNull View itemView) {
super(itemView);
imageView=itemView.findViewById(R.id.itemImageView);
itemNameTV=itemView.findViewById(R.id.itemNameTextView);
itemPriceTV=itemView.findViewById(R.id.itemPriceTextView);
itemDescTV=itemView.findViewById(R.id.itemDescritionTextView);
itemQuantity=itemView.findViewById(R.id.itemQuantity);
itemSubtract=itemView.findViewById(R.id.subtractQuantity);
itemAdd=itemView.findViewById(R.id.addQuantity);
}
}
public interface OnItemListListner{
void onItemListClick(int position);
}
}
you should have the quantity property in Item model class and have to follow the code I added below.
holder.itemAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int quantity = item[getAdapterPosition()].quantity;
quantity = quantity +1;
item[getAdapterPosition()].setQuantity(quantity);
notifyItemChanged(getAdapterPosition());
}
});
Thanks.I am sure this will work for you.
Reviewd your code and then after i'm just agreed with Harsh's Answer
there is a two way to set your adapter. most commonly used Model for storing and retriving data.
You need to create a one model class and and set data first into the model then after get data from model and set into your adapter / notify your adapter.
You need to create one variable in model class like below snippet:
public class Item {
String mQty = "";
public String getmQty() {
return mQty;
}
public void setmQty(String mQty) {
this.mQty = mQty;
}
}
Helpful Answer: Click Me
Recycler view recycles the views on scroll and resets its content, so you have to persist the quantity qty variable. You can do it by two ways
Store quantity inside your Items model.
Persist quantity in seperate HashMap as item.getId() as key and qty as value.
then get and set from the model object or hashmap.
Check updated code
holder.itemAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int intCurrentQuantity=Integer.valueOf(holder.itemQuantity.getText().toString());
++intCurrentQuantity; //use this
Log.d("myQuantity",String.valueOf(intCurrentQuantity));
holder.itemQuantity.setText(String.valueOf(intCurrentQuantity));
notifyItemChanged(holder.getAdapterPosition());
}
});
This question already has answers here:
Why doesn't RecyclerView have onItemClickListener()?
(31 answers)
RecyclerView onClick
(49 answers)
Closed 3 years ago.
I am learning Android Development. Struggling with this issue since 24 hours, need help.
On my each recycle view item I've two views ePaper & Website. I want to attach different on click listeners on the entire item, ePaper view and website view
In the above image, I need to put 3 click listeners
1. Click on red block 1 - do X (Intent to another activity)
2. Click on red block 2 - do Y (Intent to another activity)
3. Click on green block, entire item view - do Z (Dialog)
Tried many solutions. But, when I click red block, the listener in green block also comes to action in addition to listener in red block.
In the MainActivity
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getApplicationContext(),
recyclerView, new ClickListener() {
String userid = Utils.getUserId(getApplicationContext());
#Override
public void onClick(View view, final int position) {
// Set listeners here for complete card view
final NewsPapersDataModel currentPaper = newsPapersList.get(position);
Log.d("TAG","Clicked 1");
newsSelectionDialog(currentPaper.getEpaper(),currentPaper.getWebsite());
}
#Override
public void onLongClick(View view, int position) {
Toast.makeText(MainActivity.this, "Long press on position :" + position, Toast.LENGTH_LONG).show();
}
}));
In the NewsPaperAdapter
public void onBindViewHolder(#NonNull final CustomViewHolder holder, int position) {
// Log.d("TAG","Holder is "+newsList);
final NewsPapersDataModel currentItem = newsList.get(position);
final String ePaperUrl = currentItem.getEpaper();
final String webSiteUrl = currentItem.getWebsite();
final String paperName = currentItem.getName();
holder.paperNameView.setText(newsList.get(position).getName());
if (TextUtils.isEmpty(currentItem.getEpaper())) {
// Log.d("TAGG","ePaper - "+currentItem.getEpaper()+" Website - "+currentItem.getWebsite());
holder.ePaperView.setVisibility(View.GONE);
} else if (TextUtils.isEmpty(currentItem.getWebsite())) {
holder.websiteView.setVisibility(View.GONE);
}
holder.ePaperView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
saveLinksToDb(userid, "ePaper", ePaperUrl);
Intent intent = new Intent(context, NewsAdvancedWebViewActivity.class);
intent.putExtra("url", ePaperUrl);
context.startActivity(intent);
}
});
holder.websiteView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
saveLinksToDb(userid, "Website", webSiteUrl);
Intent intent = new Intent(context, NewsAdvancedWebViewActivity.class);
intent.putExtra("url", webSiteUrl);
intent.putExtra("paperName",paperName);
context.startActivity(intent);
}
});
}
Please help me.
You need to create an interface in your adapter for click listeners and add onclick methods for every item you want.
Please look into the code below.
In your adapter, create interface
public interface OnClickListener {
void onPaperViewClick(View view, int position);
void onWebsiteViewClick(View view, int position);
}
And create method to set click listener from activity
public void setOnClickListener(OnClickListener listener) {
this.onClickListener= listener;
}
And in your onBindViewHolder method,
holder.ePaperView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onClickListener.onPaperViewClick(view, position);
});
holder.websiteView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onClickListener.onWebsiteViewClick(view, position);
});
and lastly, in your activity, set
recyclerViewAdapter.setOnClickListener(new NewsPaperAdapter.OnClickListener(){
#override
void onPaperViewClick(View view, int position){
// code to handle paper click
}
#override
void onPaperViewClick(View view, int position){
// code to handle website click
}
};
Remove your TouchListener from MainActivity and add ClickListener/ LonCkickListener inside your adapter.
onBindViewHolder(){
//rest of your code
holder.itemView.setOnClickListener(new OnClickListener{
#Override
public void onClick(View view) {
// Click implementation here
}
#Override
public void onLongClick(View view) {
// Long click implementation here
}
})
}
And inside your CustomViewHolder:
public class CustomViewHolder extends RecyclerView.ViewHolder{
// Other fields
View itemView;
public CustomViewHolder(View view){
// rest of initialization
itemView = view;
}
}
EDIT (OP wants to handle application logic inside Activity)
Create an interface class named RecyclerViewActionListener:
public interface RecyclerViewActionListener {
void onViewClicked(int clickedViewId, int clickedItemPosition);
void onViewLongClicked(int clickedViewId, int clickedItemPosition);
}
Then modify your RecyclerViewAdpater to have an additional field in constructor. We will pass listener from Activity to this adpater when we create Adapter:
public class RecyclerViewAdpater extends RecyclerView.Adapter<RecyclerViewAdpater.CustomViewHolder>{
private RecyclerViewActionListener mListener;
public RecyclerViewAdpater(ArrayList<Object> yourData,RecyclerViewActionListener mListener) {
this.mListener = mListener;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false );
final CustomViewHolder holder = new CustomViewHolder(view);
holder.webView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onViewClicked(view.getId(), holder.getAdapterPosition());
}
});
holder.paperView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onViewClicked(view.getId(), holder.getAdapterPosition());
}
});
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mListener.onViewClicked(view.getId(), holder.getAdapterPosition());
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
mListener.onViewLongClicked(view.getId(), holder.getAdapterPosition());
return false;
}
});
return holder;
}
public class CustomViewHolder extends RecyclerView.ViewHolder{
// Other fields
View itemView;
View webView;
View paperView;
public CustomViewHolder(View view){
super(view);
// rest of initialization
itemView = view;
}
}
}
And then implement RecyclerViewActionListener in your Activity and override methods from RecyclerViewActionListener:
public class MainActivity extends AppCompatActivity implements RecyclerViewActionListener {
RecyclerViewAdpater adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
// Skipped for the sake of brevity
// Pass your listener to adapter here
adapter = new RecyclerViewAdpater(yourData, this );
}
#Override
public void onViewClicked(int clickedViewId, int clickedItemPosition) {
switch (clickedItemPosition){
case R.id.web_view:
// Application logic when webview clicked
break;
case R.id.paper_view:
// Application logic when paperview clicked
break;
case R.id.recyclerview_item:
// Application logic when whole item clicked
break;
}
}
#Override
public void onViewLongClicked(int clickedViewId, int clickedItemPosition) {
switch (clickedViewId){
case R.id.recyclerview_item:
// Application logic when whole item long-clicked
break;
}
}
}
And in your xml file don't forget to assign ID to you views. Because we're detecting clicked view with their IDs.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/recyclerview_item"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/web_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<ImageView
android:id="#+id/paper_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
try in your NewsPaperAdapter class onClickListner to parent layout of adapter like below
holder.parentLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final NewsPapersDataModel currentPaper = newsPapersList.get(position);
Log.d("TAG","Clicked 1");
newsSelectionDialog(currentPaper.getEpaper(),currentPaper.getWebsite());
}
});
here parentLayout is your adapter item layout root view like Relative/Linear Layout
When I click item of RecyclerView and I want to be able to open another activity. How can I do this?
This code is my recycler adapter onBindViewHolder code.
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
holder.setItemclickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
if(isLongClick){
Toast.makeText(context,"Long Click"+ dataset.get(position),Toast.LENGTH_SHORT).show();
}
else{
Intent intent=new Intent(context,MainActivity.class);
startActivity(intent);
Toast.makeText(context,"short Click"+ dataset.get(position),Toast.LENGTH_SHORT).show();
}
}`enter code here`
});
Groups tiklanilan=dataset.get(position);
holder.groupnametext.setText(tiklanilan.getGroupname());
//holder.groupimage.setImageResource(tiklanilan.getImageURL());
}
You should not use setItemClickListener but instead in your onBindViewHolder add a clickListener on your root view and call the method startActivity in that clickListener.
#Override
public void onBindViewHolder(AccountListViewHolder holder, int position) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.getContext().startActivity(yourIntent);
}
});
}
i have recyclerview and button on the all item of list. when i click the button in my adapter item deleted and i want refresh recycler and show new data.
#Override
public void onBindViewHolder(final LietnerViewHolder holder, final int position) {
lietner = lietners.get(position);
holder.txt_en.setText(lietner.getText_en());
holder.txt_pe.setText(lietner.getText_pe());
holder.time.setText(lietner.getTime());
holder.data.setText(HelperCalendar.g2j(lietner.getTime_create()));
holder.next_level.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
G.databaseOpenHelper.goToNextLevel(lietners.get(position).getId());
}
});
}
For re-initializing the recycler view and get callback on onBindViewHolder
simple call notifyDataSetChanged();
#Override
public void onBindViewHolder(final LietnerViewHolder holder, final int position) {
lietner = lietners.get(position);
holder.next_level.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// delete the item, or change the data.
notifyDataSetChanged();
}
});
}
i do this and it work for me!
#Override
public void onBindViewHolder(final LietnerViewHolder holder, final int position) {
lietner = lietners.get(position);
holder.txt_en.setText(lietner.getText_en());
holder.txt_pe.setText(lietner.getText_pe());
holder.time.setText(lietner.getTime());
holder.data.setText(HelperCalendar.g2j(lietner.getTime_create()));
holder.next_level.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
G.databaseOpenHelper.goToNextLevel(lietners.get(position).getId());
lietners.remove(position);
notifyDataSetChanged();
}
});
}